{"id":25813,"date":"2023-09-15T18:04:39","date_gmt":"2023-09-15T16:04:39","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=25813"},"modified":"2023-09-15T18:04:43","modified_gmt":"2023-09-15T16:04:43","slug":"cost-efficient-server-structure-merging-static-and-dynamic-api","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/cost-efficient-server-structure-merging-static-and-dynamic-api\/","title":{"rendered":"Cost-Efficient Server Structure: Merging Static and Dynamic API"},"content":{"rendered":"\n<p>While <a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/?p=25865\" target=\"_blank\" rel=\"noopener\" title=\"Learn more about how we built the game.\">developing our guessing game<\/a>, <a href=\"https:\/\/moreorless.io\/\" target=\"_blank\" rel=\"noopener\" title=\"&quot;More or Less&quot;\">&#8220;More or Less&#8221;<\/a>, we found a method to significantly reduce traffic on our serverless API, leading to cost savings and an improved content creation experience.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">The Problem<\/h2>\n\n\n\n<p>In our game, players can contribute their own game modes, using the web editor.&nbsp;<\/p>\n\n\n\n<p>Additionally, we develop game modes ourselves to guarantee high-quality content for trendings topics. These own created game modes are featured on the discover pages and played a lot, subsequently leading to increased costs in API usage.<\/p>\n\n\n\n<p>So generally spoken:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Websites usually have featured <strong>content or items on the landing page that get viewed many times<\/strong>, leading to higher costs in the API.<\/li>\n\n\n\n<li>This content is often <strong>created by the website owner<\/strong> rather than coming from community contributions.<\/li>\n<\/ul>\n\n\n\n<p>Confronted with this scenario, we posed ourselves a challenge:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>How can we <strong>reduce the dynamic API traffic<\/strong> and consequently, the associated costs?<\/li>\n\n\n\n<li>How can we <strong>simplify the process<\/strong> for us <strong>to contribute our content<\/strong>, making it as effortless as possible?<\/li>\n<\/ul>\n\n\n\n<p>To address this challenge, we need to understand static and dynamic APIs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">Static API<\/h2>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\">What is a Static API?<\/h3>\n\n\n\n<p>A Static API is an API that <strong>delivers its data<\/strong> in the form of <strong>static, pre-generated JSON files<\/strong> hosted on a content delivery network (CDN) rather than depending on real-time database queries or actions executed on a server.<\/p>\n\n\n\n<p>Read more about static APIs and a detailed list of their pros and cons <a href=\"https:\/\/www.seancdavis.com\/posts\/lets-talk-about-static-apis\/\" target=\"_blank\" rel=\"noopener\" title=\"here\">here<\/a>.&nbsp;<\/p>\n\n\n\n<p>If we take a look at our challenge, we consider the following.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">Pro: Cost-effective content delivery<\/h3>\n\n\n\n<p>With a static API we can <strong>publish our content at zero cost <\/strong>(0$). There are several platforms, which offer to host around 20 000 static files per project, for zero dollars. For our guessing game <a href=\"https:\/\/moreorless.io\/\" target=\"_blank\" rel=\"noopener\" title=\"&quot;More or Less&quot;\">&#8220;More or Less&#8221;<\/a>, we decided to go with <a href=\"https:\/\/pages.cloudflare.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Cloudflare Pages.\">Cloudflare Pages.<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">Pro: Effortless content creation<\/h3>\n\n\n\n<p>Another advantage, for us is, the creation of the data itself. Using a web editor can be an easy and intuitive experience for normal users, but for us as superusers, we would love to have benefits we already know like <strong>automation, version control<\/strong> (git) and working in files instead of form fields.&nbsp;<\/p>\n\n\n\n<p style=\"padding-top:0;padding-bottom:0\"><strong>But<\/strong> <strong>remember<\/strong>: This doesn&#8217;t have to mean that\u2019s the right way for everyone: In your own project, think about, who is submitting the data? What tools do they like and use? Ask them in which way they would like to create the content.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">Cons: But it\u2019s (delivered) static\u2026<\/h3>\n\n\n\n<p>On the other hand, the disadvantages are that we can <strong>not easily submit data<\/strong> from requests going to our API and there&#8217;s <strong>no user authentication mechanism<\/strong>.&nbsp;<\/p>\n\n\n\n<p>Meaning a static API is good for game modes created by us but it is not the right when working with user generated game modes. For this we require a <strong>Dynamic API <\/strong>(the API you probably already know).<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">What is a Dynamic API?&nbsp;<\/h2>\n\n\n\n<p>A Dynamic API <strong>runs on a web server<\/strong> and <strong>interacts in real-time with databases<\/strong> or other systems to dynamically respond to user queries and actions. It supports access control (authentication and authorization), data creation and manipulation, and can adapt to varying user demands.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">Pro: Works well with user data<\/h3>\n\n\n\n<p>In other words, using a dynamic API for our user generated game modes fits perfectly because users can <strong>submit and read data<\/strong> from the API. With the benefits of having access control we can control which data a user can modify and implement private game modes.&nbsp;&nbsp;<\/p>\n\n\n\n<p>To keep the focus on the functional user requirements we decided to use <a href=\"https:\/\/firebase.google.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Firebase\">Firebase<\/a>, with Firestore, for the dynamic data.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">Cons: But dynamic data costs money\u2026<\/h3>\n\n\n\n<p>In the most serverless environments, also in Firebase, every time you access or retrieve data, there are associated monetary costs. So you have to try to keep these at a minimum.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">Solution: Merging Static and Dynamic&nbsp;<\/h2>\n\n\n\n<p>To fix our problems we can <strong>combine both kinds, static and dynamic<\/strong>. We store and maintain our own created game modes with a static API and do all the user created game modes with a dynamic API.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">Why should you combine (Pros)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Reduced Server Costs<\/strong>: The static API is completely free of platform charges. Content which comes from the static API can reduce the costs at your dynamic API a lot.&nbsp;<\/li>\n\n\n\n<li><strong>Scalability<\/strong>: Another benefit is the reduction of traffic to your dynamic API. If you have troubles scaling your system at spike times you can shift a lot of traffic from your dynamic API, leading to reduced server load.<\/li>\n\n\n\n<li><strong>Improved Performance<\/strong>: CDNs, where static APIs are deployed, distribute static content to edge locations worldwide, reducing the distance between users and the content they request. This results in lower latency, improved user experience, and faster loading times. Plus, it reduces the load on your dynamic API, leading to faster response times there as well.<\/li>\n\n\n\n<li><strong>Easier content creation<\/strong>: You can speed up content creation. If you use methods, which are known by the content creators, they can maintain content faster, easier and with more fun. Additionally you can automate many things without the need to modify your web editor.&nbsp;<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:0\">When you should not combine (Cons)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Complexity<\/strong>: Combining static and dynamic APIs can be complex, requiring extra effort to integrate and maintain both effectively. In your project, think of how complex your application or data model is and if it\u2019s worth going the extra mile.<\/li>\n\n\n\n<li><strong>Increased development costs:&nbsp; <\/strong>Developers need to invest effort in implementing the additional API, which can lead to increased development costs. Consider which causes more costs in the end, the development process or the hosting costs?&nbsp;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">How to implement?&nbsp;<\/h2>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\">Create a Static API<\/h3>\n\n\n\n<p>First you have to create your own static API. This is how we did it:&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>1. Define a suitable data input model<\/strong><\/h4>\n\n\n\n<p>Think of how you would like to store or get your data. Do you want to use a database? Do you want to fetch a certain API? Do you want to use files?&nbsp;<\/p>\n\n\n\n<p>You don\u2019t have to think of an optimal structure for your web consumption yet.&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>2. Generate the Data<\/strong><\/h4>\n\n\n\n<p>In the next step you have to write a service which generates a static version of your data in the form of files. First, plan which endpoints you would like to offer in your API? After that you have to write a service which converts your input data into data portions which you finally write into a static file. The most common format is JSON.<\/p>\n\n\n\n<p>You can include list files with minimal data, single view files with detailed data, pagination for your list files and so on.<\/p>\n\n\n\n<p>You can also compress and deliver image assets at this point.<\/p>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>3. Serve the Data<\/strong><\/h4>\n\n\n\n<p>Your generated data now has to be accessible from the internet. Host the generated files on any static file hosting platform. This could be a traditional web server, a cloud storage solution like <a href=\"https:\/\/aws.amazon.com\/de\/pm\/serv-s3\/?trk=87635f19-6e93-4215-99c4-d52f0cd3a835&amp;sc_channel=ps&amp;ef_id=CjwKCAjwgZCoBhBnEiwAz35Rwi2WQLUWrkegoVotGhf-yI9o2EcXJaRSHreuQF7GKFJyi_eHZSR0yRoCAKoQAvD_BwE:G:s&amp;s_kwcid=AL!4422!3!645133625277!e!!g!!amazon%20s3!19579657901!143689753125\" target=\"_blank\" rel=\"noopener\" title=\"Amazon S3\">Amazon S3<\/a>, or a specialized static hosting service like <a href=\"https:\/\/www.netlify.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Netlify\">Netlify<\/a>, <a href=\"https:\/\/pages.github.com\/\" target=\"_blank\" rel=\"noopener\" title=\"GitHub Pages\">GitHub Pages<\/a>, or <a href=\"https:\/\/vercel.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Vercel\">Vercel<\/a>. If you are under 20 000 files we recommend you to go with a static hosting service. They are mostly free and offer easy integration into GitHub Actions or Gitlab CI\/CD. You can define a stable branch in your repo and automate the deployment of your static API. This makes the deployment of your data very easy.&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>4. Basic Access Control (Optional)<\/strong><\/h4>\n\n\n\n<p>Sometimes it makes sense to limit your API with CORS to prevent other websites from just consuming it. Most hosting services offer this for free.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">Another problem: How to add dynamic data to your static data?&nbsp;<\/h3>\n\n\n\n<p>In our game, we maintain high scores for both:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Games we&#8217;ve created, sourced from the static API.<\/li>\n\n\n\n<li>User-generated games, sourced from Firebase.<\/li>\n<\/ul>\n\n\n\n<p>How can we add dynamic highscores to the static games?&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>Structure your data to split the \u201cmust-be\u201d dynamic parts?&nbsp;<\/strong><\/h4>\n\n\n\n<p>To incorporate dynamic highscores into static game data, we followed these steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Identify Dynamic Data<\/strong>: Determine which parts of your data need to be dynamic.<\/li>\n\n\n\n<li><strong>Organize Your Data<\/strong>: Move the dynamic components into separate collections within the dynamic API.<\/li>\n\n\n\n<li><strong>Use Both APIs<\/strong>: Once separated, continue to use the static API for standard game data. For any dynamic elements, like highscores, refer to the dynamic API.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30);padding-right:0;padding-bottom:0;padding-left:0\">How to handle this in the frontend client?&nbsp;<\/h3>\n\n\n\n<p>Your frontend client has the responsibility of <strong>deciding which API to query static or dynamic<\/strong>. Let\u2019s say the user wants to play a game with a certain ID.&nbsp; We found two strategies on how you can do it.<\/p>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>Static First Approach<\/strong><\/h4>\n\n\n\n<p>This approach optimizes for reduced costs and improved performance. By default, always attempt to fetch from the static API first:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Attempt Static Fetch<\/strong>: Initially, always try fetching data from the static API.<\/li>\n\n\n\n<li><strong>Fallback to Dynamic<\/strong>: If the required game mode or data isn&#8217;t found in the static data (e.g., because it\u2019s user-generated), fall back to querying the dynamic API.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\" data-line=\"\">const [game, setGame] = useState(null);\n\nuseEffect(() =&gt; {\n\tconst loadGame = async () =&gt; {\n\t\t\/\/ First, try to get the game data from a static source\n\t\tlet game = await getStaticGame(id);\n\t\t\n\t\t\/\/ If the game data wasn&#039;t found in the static source, try to get it from Firebase\n\t\tif (!game) {\n\t\t\tgame = await getFirebaseGame(id);\n\t\t}\n\t\t\n\t\t\/\/ If the game data wasn&#039;t found in both sources, throw a 404 error\n\t\tif (!game) {\n\t\t\tthrow Error(404);\n\t\t}\n\t\t\n\t\tsetGame(game);\n\t}\n\t\n\tloadGame();\n}, [id]); <\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading has-medium-font-size\"><strong>Fetching IDs for Static and Then Deciding<\/strong><\/h4>\n\n\n\n<p>Instead of directly fetching the data, another approach is to fetch identifiers or metadata first:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Fetch Metadata<\/strong>: Start by fetching a list of game IDs from the static API.<\/li>\n\n\n\n<li><strong>Decide on API Type<\/strong>: Once you have the static game IDs, the frontend client can easily determine which API to use for fetching detailed game data.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\" data-line=\"\">const [staticGameIds, setStaticGameIds] = useState([]);\n\n\/\/ Fetch the list of game IDs from the static API\nuseEffect(() =&gt; {\n\tconst fetchStaticGameIds = async () =&gt; {\n\t\tconst ids = await getStaticGameIds(); \n\t\tsetStaticGameIds(ids);\n\t}\n\t\n\tfetchStaticGameIds();\n}, []);<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\" data-line=\"\">const [game, setGame] = useState(null);\n\n\/\/ Fetch the game data from the static API or the Firebase API\nuseEffect(() =&gt; {\n\tconst loadGame = async () =&gt; {\n\t\tlet gameData;\n\t\t\n\t\t\/\/ Check if the &#039;id&#039; is in the list of static game IDs\n\t\tif (staticGameIds.includes(id)) {\n\t\t\tgameData = await getStaticGame(id);\n\t\t} else {\n\t\t\tgameData = await getFirebaseGame(id);\n\t\t}\n\n\t\tif (!gameData) {\n\t\t\tthrow Error(404);\n\t\t}\n\n\t\tsetGame(gameData);\n\t}\n\n\tloadGame();\n}, [id, staticGameIds]);<\/code><\/pre>\n\n\n\n<p>For both strategies ensure if you create your IDs that they are unique.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">Why Weren&#8217;t Firebase Bundles Our Solution?<\/h3>\n\n\n\n<p>When faced with the challenge of optimizing server costs and improving content creation, many might wonder: Why didn\u2019t we just use Firebase Bundles?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Pricing Issue Remains Unresolved<\/strong>: The most significant challenge we were trying to address was the high API usage costs. By transitioning to a Static API for our created game modes, we eliminate these costs altogether. With Firebase Bundles, however, the pricing issue would persist because the pricing structure is fundamentally the same.<\/li>\n\n\n\n<li><strong>Missing Git Advantages<\/strong>: One of our primary objectives was to streamline the content creation process for ourselves. Integrating data management with Git brought several benefits to the table:\n<ul class=\"wp-block-list\">\n<li><strong>Version Control<\/strong>: With Git, every change is tracked. This offers an advantage in managing content. If a mistake is made or if we wish to revert to a previous version of the game mode, Git allows us to do so effortlessly.<\/li>\n\n\n\n<li><strong>Automation Possibilities<\/strong>: Utilizing Git opened doors for automation. By integrating with CI\/CD pipelines like GitHub Action, content deployment becomes easy. Automatic data generation, testing, and deployment are possible without the need for manual interventions.&nbsp;<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\" style=\"padding-top:var(--wp--preset--spacing--30)\">Conclusion<\/h2>\n\n\n\n<p>In our journey to optimize our guessing game <a href=\"https:\/\/moreorless.io\/\" target=\"_blank\" rel=\"noopener\" title=\"&quot;More or Less&quot;\">&#8220;More or Less&#8221;<\/a>, we combined static and dynamic APIs, achieving significant cost savings and content creation efficiency. While not every project will benefit from this hybrid approach, we think we did by rethinking traditional server structures.<\/p>\n\n\n\n<p>Now put your skills to the test: Dive into our game and <a href=\"https:\/\/moreorless.io\/game\/commit-clash\" target=\"_blank\" rel=\"noopener\" title=\"guess which repository has more commits\">guess which repository has more commits<\/a>.<\/p>\n\n\n\n<p>Our highscore was 23, are you able to beat that? \ud83d\ude09<\/p>\n\n\n\n<p>Happy Guessing!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While developing our guessing game, &#8220;More or Less&#8221;, we found a method to significantly reduce traffic on our serverless API, leading to cost savings and an improved content creation experience.&nbsp; The Problem In our game, players can contribute their own game modes, using the web editor.&nbsp; Additionally, we develop game modes ourselves to guarantee high-quality [&hellip;]<\/p>\n","protected":false},"author":1143,"featured_media":25844,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,120,656,21,651,657,662],"tags":[993,7,536,995,981,991,994],"ppma_author":[670,984],"class_list":["post-25813","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-allgemein","category-cloud-technologies","category-databases","category-system-architecture","category-system-designs","category-teaching-and-learning","category-web-performance","tag-api-design","tag-cloud","tag-cloud4dev","tag-dynamic-api","tag-firebase","tag-software-development-for-cloud-computing","tag-static-api"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/2_cost_efficient_server_structure_merging_static_and_dynamic_api.png","jetpack-related-posts":[{"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":25813,"position":0},"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":25863,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/optimizing-list-views-structuring-data-efficiently-in-firestore\/","url_meta":{"origin":25813,"position":1},"title":"Optimizing List Views: Structuring Data Efficiently in Firestore","author":"js409","date":"15. September 2023","format":false,"excerpt":"While developing our guessing game \"More or Less\", we encountered a common challenge many developers face: determining the structure of our data model. Challenge 1: List vs. Detailed View Many websites show an excerpt of their content in a list view. In our \u201cMore or Less\u201d game, for example, we\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\/3_optimizing_list_views_structuring_data_efficiently_in_firestore.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\/3_optimizing_list_views_structuring_data_efficiently_in_firestore.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/3_optimizing_list_views_structuring_data_efficiently_in_firestore.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/3_optimizing_list_views_structuring_data_efficiently_in_firestore.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/3_optimizing_list_views_structuring_data_efficiently_in_firestore.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":11267,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/29\/montagsmaler-multiplayer-online-game-running-on-amazon-web-services\/","url_meta":{"origin":25813,"position":2},"title":"Montagsmaler \u2013 Multiplayer online game running on Amazon Web Services","author":"ns107","date":"29. September 2020","format":false,"excerpt":"by Jannik Smidt (js343), Niklas Schildhauer (ns107) and Lucas Cr\u00e4mer (lc028) Project idea Montagsmaler is a multiplayer online game for web browsers. The idea is derived from the classic Pictionary game, where players have to guess what one person is painting. Basically, we have built the digital version of it,\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\/2020\/09\/Untitled-Diagram.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/Untitled-Diagram.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/Untitled-Diagram.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/Untitled-Diagram.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":8681,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/08\/31\/using-googles-cloud-vision-api-to-create-a-receipt-analyzer\/","url_meta":{"origin":25813,"position":3},"title":"Using Google&#8217;s Cloud Vision API to create a Receipt Analyzer","author":"sh260","date":"31. August 2019","format":false,"excerpt":"Everyone knows the problem of keeping track of expenses. Many applications offer an overview of all expenses, but entering all data individually can be quite time-consuming. To overcome this task, we have developed SWAI, 'A Scanner with A.I.'.","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\/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\/2019\/08\/grafik-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/grafik-1.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/grafik-1.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/grafik-1.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":926,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/07\/26\/socialcloud-configure-all-the-things-part-6\/","url_meta":{"origin":25813,"position":4},"title":"SocialCloud &#8211; Configure all the things! &#8211; Part 6","author":"ew033","date":"26. July 2016","format":false,"excerpt":"One of the requirements of the system is that organizations should be able to set up and deploy the HumHub system on their own. For this purpose, we have designed the Configtool. To meet this requirement we have to use different tools, procedures and interfaces from Bluemix. In the following\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\/2016\/07\/socialCloud.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/07\/socialCloud.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/07\/socialCloud.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/07\/socialCloud.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/07\/socialCloud.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":4190,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/08\/31\/yourtube-a-simple-video-platform-in-you-personal-amazon-cloud\/","url_meta":{"origin":25813,"position":5},"title":"YourTube &#8211; A simple video platform in you personal amazon cloud","author":"nk078","date":"31. August 2018","format":false,"excerpt":"During the Dev4Cloud Levture i created a simple static webpage that uses Amazons S3 service for Hosting and video storage and amazons cognito for user authentification and role managemant. Design considerations. The platform was designed with simplicity in mind and there for i decided to go with as few services\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":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":670,"user_id":1143,"is_guest":0,"slug":"michael_cabanis","display_name":"mc071","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/86026021a9dba15aa2e103b3ae5843b86b86a8942835a44889d70fccb60609b2?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""},{"term_id":984,"user_id":1166,"is_guest":0,"slug":"jasmin-joy_springer","display_name":"js409","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/1f6b0be7c4d382e4436df225487fc66cd74c3f9b03189343fc7a76e2be638862?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\/25813","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\/1143"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=25813"}],"version-history":[{"count":22,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/25813\/revisions"}],"predecessor-version":[{"id":25971,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/25813\/revisions\/25971"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media\/25844"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=25813"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=25813"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=25813"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=25813"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}