<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Webdevelopment Archives - Mobile USTP MKL</title>
	<atom:link href="https://mobile.fhstp.ac.at/category/development/webdevelopment/feed/" rel="self" type="application/rss+xml" />
	<link>https://mobile.fhstp.ac.at/category/development/webdevelopment/</link>
	<description>Die &#34;Mobile Forschungsgruppe&#34; der USTP, sie  sammelt hier alles zu den Themen Design, UX und Entwicklung mobiler Applikationen</description>
	<lastBuildDate>Thu, 12 Mar 2026 12:50:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://mobile.fhstp.ac.at/wp-content/uploads/2025/03/icon-120x120.webp</url>
	<title>Webdevelopment Archives - Mobile USTP MKL</title>
	<link>https://mobile.fhstp.ac.at/category/development/webdevelopment/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Projekt &#124; bHere &#8211; not on your phone</title>
		<link>https://mobile.fhstp.ac.at/studium/studium-projekte/blog-bhere-not-on-your-phone/</link>
		
		<dc:creator><![CDATA[David Grünberger]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 23:13:34 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Dokumentation]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[Tests]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Bluetooth Low Energy]]></category>
		<category><![CDATA[digital-wellbeing]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[mesh]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[Semesterprojekt]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15451</guid>

					<description><![CDATA[<p>Im 3. Semester des Master-Studiengangs Interactive Technologies (Masterklasse Mobile) stand das große Semestergruppenprojekt an. Als ganze Masterklasse (insgesamt 8 Personen) entwickelten wir über das ganze Semester hinweg bHere, eine soziale App, die Gruppen durch spielerische Mechaniken und Konsequenzen motiviert, beim gemeinsamen Ausgehen das Handy wegzulegen. Aufgabenstellung Die einzige Vorgabe war, dass das Projekt eine technische <a class="read-more" href="https://mobile.fhstp.ac.at/studium/studium-projekte/blog-bhere-not-on-your-phone/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/studium/studium-projekte/blog-bhere-not-on-your-phone/">Projekt | bHere &#8211; not on your phone</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Im 3. Semester des Master-Studiengangs Interactive Technologies (Masterklasse Mobile) stand das große Semestergruppenprojekt an. Als ganze Masterklasse (insgesamt 8 Personen) entwickelten wir über das ganze Semester hinweg bHere, eine soziale App, die Gruppen durch spielerische Mechaniken und Konsequenzen motiviert, beim gemeinsamen Ausgehen das Handy wegzulegen.</p>



<h2 class="wp-block-heading">Aufgabenstellung</h2>



<p>Die einzige Vorgabe war, dass das Projekt eine technische Herausforderung beinhalten muss. Nachdem wir drei Ideen gesammelt hatten, entschieden wir uns dazu, eine App zu entwickeln, die Menschen motiviert, die Zeit wieder mehr mit ihren Liebsten zu genießen, ohne auf das Handy zu schauen. Die technische Herausforderung lag hierbei vor allem in der Verbindung zwischen den Geräten durch Bluetooth, aber auch in der Erstellung einer nativen, production-ready App.</p>



<h3 class="wp-block-heading">MVP</h3>



<p>Anfangs wurde von uns selbst ein MVP mit den grundlegendsten Funktionen definiert. Dazu zählte, sich als User einloggen bzw. registrieren und Sessions starten zu können, in der das Handy nicht verwendet werden sollte. Weiters ist es wichtig, die Verbindung zwischen den Geräten (egal ob NFC, BLE etc.) herzustellen und aufrechtzuerhalten. Die App sollte erkennen, wenn jemand das Handy verwendet, und das den anderen Geräten mitteilen. Wir hatten die Idee, dass die User*innen mehrere Modi spielen können, wobei nur der “Bill Splitter” zum MVP zählt. Dabei sollte man einen Rechnungsbetrag eingeben können und die App zeigt an, wer wie viel schlussendlich zahlen muss, basierend darauf, wie oft jeweils das Handy verwendet wurde. Die App sollte grundsätzlich nativ auf beiden Plattformen (iOS und Android) entwickelt werden und am Ende production-ready sein. Zudem hatten wir uns vorgenommen, eine CI/CD-Pipeline fürs Backend aufzusetzen und eine Website mit rechtlichen Informationen und Links zur App zu entwickeln. Die Website spielt vor allem für die Releases in den Stores eine Rolle.</p>



<h3 class="wp-block-heading">Nice To Have</h3>



<p>Als “Nice To Have” hatten wir uns primär die Erweiterung um 2 zusätzliche Modi vorgenommen: Beim Modus “Pot Lock” legen die Spieler*innen anfänglich fest, welcher Betrag pro Person in einen virtuellen Topf gegeben werden soll, und ab welcher Handynutzungsgrenze (“Threshold”) man seinen Einsatz verliert. Am Schluss teilen sich die Personen, die den Threshold nicht überschritten haben, den Topf. Beim Modus “Group Jar” legt die Gruppe einen Preis pro Handynutzung fest und am Ende der Session sagt die App, wer wie viel insgesamt in die Gruppenkasse zahlen muss.</p>



<p>Weitere Nice-To-Haves waren die Möglichkeit, dass Spieler*innen auch mittendrin einer Session beitreten können (falls jemand sich z. B. verspätet), dass sie sich nach einem Disconnect wieder reconnecten können und dass sie auch früher die Session verlassen können (falls jemand z. B. schon früher nach Hause gehen muss). Abgesehen davon wollten wir, dass die App auch komplett offline funktioniert, damit man sie auch in einer Keller-Bar mit schlechtem Empfang nutzen kann. Zusätzlich wollten wir die App zumindest in einem Store veröffentlichen.</p>



<p>Weiters hatten wir viele coole Ideen, die App durch Features wie Mini Games, einer KI-Funktion zum Rechnung-Scannen (für den Modus “Bill Splitter”), einer History, einem Streak, einer Realtime Abstimmung (für Notfallsituationen, in denen die Handynutzung toleriert wird), einem SSO-Login und einer direkten Zahlung in der App bzw. einer Importfunktion in eine App wie Splitwise oder Tricount zu erweitern, allerdings blieb dafür leider keine Zeit mehr &#8211; zumindest in diesem Semester. <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h2 class="wp-block-heading">Verwendete Technologien</h2>



<h3 class="wp-block-heading">App</h3>



<p>Die Apps wurden jeweils nativ, in Swift für iOS und Kotlin für Android geschrieben, um Erfahrung im Bereich der nativen App-Entwicklung zu sammeln.</p>



<h3 class="wp-block-heading">Website</h3>



<p>Die Website wurde mit Next.js, einem React-basierten Framework entwickelt. Für das Styling wurde Tailwind CSS verwendet und für eine typsichere Entwicklung haben wir uns für TypeScript entschieden. Wir verwenden eine klassisch komponentenbasierte Architektur mit wiederverwendbaren Komponenten. Für die Containerisierung verwenden wir Docker.</p>



<h2 class="wp-block-heading">Projektablauf</h2>



<p>Die Arbeit am Semesterprojekt wurde in Sprints aufgeteilt (die an Masterklassen-Einheiten orientiert waren, wobei wir intern auch hin und wieder Meetings dazwischen hatten, wenn der Abstand zwischen den Masterklassen Einheiten zu lange war).</p>



<p>Als Projektmanagement-Tool und zum Verwalten des Backlogs wurde die Software &#8220;Linear&#8221; verwendet: vor jedem Sprint definierten wir, wer an welchen Tickets arbeitet und teilten diese im Team auf.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="3819" height="1440" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere6.jpg" alt="" class="wp-image-15471" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere6.jpg 3819w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere6-1536x579.jpg 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere6-2048x772.jpg 2048w" sizes="(max-width: 3819px) 100vw, 3819px" /><figcaption class="wp-element-caption"><strong>Abb. 1: Beispielsprint in unserem Linear-Setup</strong></figcaption></figure>



<h2 class="wp-block-heading">Das Endprodukt</h2>



<p>Wir haben die MVP Funktionalitäten und Nice-To-Haves wie beschrieben umgesetzt, mit den folgenden kleinen Anpassungen: Unsere App funktioniert komplett offline mit Bluetooth LE und die Session ID wird über das Scannen eines QR-Codes unter den Spieler*innen ausgetauscht. Das Backend hatten wir zwar anfänglich aufgesetzt, es wird momentan allerdings nicht benötigt. Zusätzlich zu den 3 Modi gibt es nun auch einen vierten Modus, das “Basic Leaderboard”, mit welchem sich User*innen ihre eigenen Regeln festlegen können. Weiters implementierten wir einen Solomodus, sodass die App nicht nur in der Gruppe, sondern auch alleine (z. B. beim Lernen) verwendet werden kann. Außerdem setzten wir eine coole CI/CD Pipeline für unsere Website auf und veröffentlichten unsere App in nicht nur einem, sondern in beiden Stores (Apple App Store, Google Play Store).</p>



<p class="has-medium-font-size"><a href="https://apps.apple.com/de/app/bhere-not-on-your-phone/id6757390918" target="_blank" rel="noreferrer noopener">Link zum iOS App Store-Eintrag</a></p>



<p class="has-medium-font-size"><a href="https://play.google.com/store/apps/details?id=app.bhere" target="_blank" rel="noreferrer noopener">Link zum Android App Store-Eintrag</a></p>



<figure class="wp-block-image size-full"><img decoding="async" width="1885" height="1336" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere1.jpg" alt="" class="wp-image-15457" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere1.jpg 1885w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere1-1536x1089.jpg 1536w" sizes="(max-width: 1885px) 100vw, 1885px" /><figcaption class="wp-element-caption"><strong>Abb. 2: Produkt-Teaser aus dem App Store</strong></figcaption></figure>



<p>Beim ersten Öffnen der App wird man durch ein Onboarding geleitet, in welchem die App kurz vorgestellt wird. Hierbei muss man auch einen Namen angeben, welcher innerhalb der App für einen selbst verwendet werden soll. Schließlich landet man am Homescreen (Abb. 3, links). Über das Profil-Icon rechts oben hat man die Möglichkeit, den festgelegten Namen zu ändern. Über den Button “Start New Session” startet man eine neue Gruppensession und kommt zum New Session Screen (Abb. 3, Mitte) &#8211; diesen Button muss allerdings nur eine Person in der Gruppe klicken. Alle anderen klicken auf “Join Session”, welcher die Kamera öffnet, um den generierten QR-Code zu scannen, welcher einen dann auch zum New Session Screen weiterleitet. Der Button “Go Solo” führt zum Solomodus, welcher weiter unten genauer beschrieben wird.</p>



<p>Am New Session Screen werden die aktuellen Teilnehmer*innen und der ausgewählte Modus angezeigt. Der “Host” der Session (die Person, die auf “Start New Session” geklickt hat) hat zudem die Möglichkeit, den Modus auszuwählen (Abb. 3, rechts) und notwendige Einstellungen vorzunehmen (z. B. den Preis pro Nutzung für den Group Jar Modus zu setzen).</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1891" height="1144" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere2.jpg" alt="" class="wp-image-15459" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere2.jpg 1891w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere2-1536x929.jpg 1536w" sizes="(max-width: 1891px) 100vw, 1891px" /><figcaption class="wp-element-caption"><strong>Abb. 3: iOS App Screenshots</strong></figcaption></figure>



<p>Wie angekündigt, gibt es auch einen Solomodus. Mit dem Klick auf “Go Solo” am Home Screen kommt man zum New Focus Session Screen (Abb. 4, links), welcher wie ein Group Jar Modus funktioniert &#8211; man muss also den Preis pro Nutzung festlegen. Während der Session (Focus Session Screen, Abb. 4, rechts) sieht man die gesamte Nutzungsanzahl und wie viel Geld man sich in das eigene Sparschwein zahlen müssen wird.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1887" height="1144" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere3.jpg" alt="" class="wp-image-15460" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere3.jpg 1887w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere3-1536x931.jpg 1536w" sizes="auto, (max-width: 1887px) 100vw, 1887px" /><figcaption class="wp-element-caption"><strong>Abb. 4: iOS App Screenshots</strong></figcaption></figure>



<p>Ein weiteres spannendes Feature ist das Starten des Solomodus durch das Ablegen des Handys auf eine bestimmte Stelle. Wir stellen uns den Ablauf für User*innen folgendermaßen vor:</p>



<ol class="wp-block-list">
<li>User*in setzt sich an den Schreibtisch.</li>



<li>User*in legt das Handy auf eine Ablagefläche.</li>



<li>bHere App öffnet sich und Solomodus wird automatisch gestartet.</li>
</ol>



<figure class="wp-block-video"><video controls src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/NFC-Solomodus.mp4"></video><figcaption class="wp-element-caption"><strong>Video. 1: Starten des Solomodus per NFC-Tag</strong></figcaption></figure>



<p>Technisch funktioniert es mit einem NFC-Tag, der einen Deeplink enthält. Für die Projektevernissage 2026 haben wir 100 Tags (NTAG215) bestellt, beschrieben und hergeschenkt. Das Feature haben wir aktuell nur für Android implementiert.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="3382" height="1378" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere4.jpg" alt="" class="wp-image-15467" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere4.jpg 3382w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere4-1536x626.jpg 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere4-2048x834.jpg 2048w" sizes="auto, (max-width: 3382px) 100vw, 3382px" /><figcaption class="wp-element-caption"><strong>Abb. 5: Android App Screenshots (Dark Mode Support)</strong></figcaption></figure>



<p>Die App ist auf beiden Plattformen sowohl in Light Mode, als auch in Dark Mode, verfügbar. </p>



<h2 class="wp-block-heading">Feedback und Verbesserungsmöglichkeiten</h2>



<p>Durch die Teilnahme an der Projektvernissage konnten wir wertvolles User-Feedback für potentielle zukünftige Erweiterungen und Verbesserungen der App sammeln: der wohl größte Pain Point der aktuellen Lösung ist die Latenz des implementierten BLE-Mesh. Vor allem bei Sessions mit einer hohen Teilnehmeranzahl kann es aktuell bis zu mehreren Minuten dauern, bis alle Daten zwischen allen Geräten ausgetauscht wurden. Sollte das Projekt noch weiterentwickelt werden, wäre das wohl eines der ersten Tickets, das umgesetzt werden müsste.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1768" height="1222" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere5.jpg" alt="" class="wp-image-15469" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere5.jpg 1768w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/bhere5-1536x1062.jpg 1536w" sizes="auto, (max-width: 1768px) 100vw, 1768px" /><figcaption class="wp-element-caption"><strong>Abb. 6: Einer unserer beiden Stände auf der Projektvernissage</strong></figcaption></figure>



<h2 class="wp-block-heading">Fazit aller Teilnehmer*innen</h2>



<p>Im folgenden Abschnitt möchten wir noch unser Fazit und unsere Erfahrungen teilen, die wir im Zuge dieses Semestergruppenprojekts sammeln konnten.</p>



<h3 class="wp-block-heading">David</h3>



<p>Die Arbeit an bHere war für mich eine intensive und lehrreiche Erfahrung. Technisch gesehen war die Implementierung der Bluetooth-Low-Energy-Kommunikation sicherlich die größte Hürde. Es hat einige Iterationen und Research gebraucht, weshalb ich umso stolzer bin, dass wir schlussendlich ein funktionierendes BLE-Mesh auf die Beine stellen konnten.</p>



<p>Eine wichtige Lektion war für mich die Herausforderung der parallelen Entwicklung auf zwei Plattformen. Es zeigte sich schnell: Wenn Details nicht vorab klar definiert sind, kann es passieren, dass sie auf iOS und Android unterschiedlich umgesetzt werden. Das führte dazu, dass die letzten Wochen und Tage vor der Abgabe besonders intensiv waren, da wir viele dieser kleinen Unstimmigkeiten noch angleichen mussten. Auch den Prozess der Veröffentlichung hatte ich unterschätzt – insbesondere die Vorbereitung des Store-Eintrags und die zwingende 14-tägige Testphase im Google Play Store benötigen mehr Vorlaufzeit, als man zu Beginn vermuten würde.</p>



<h3 class="wp-block-heading">Andreas</h3>



<p>Anders als bei der einwöchigen WildWeek, die wir im Laufe des 2. Semesters hatten, wurden wir in diesem Semester in einem technisch herausfordernden Semesterprojekt auf die Probe gestellt. Dies forderte ein hohes Maß an Eigenverantwortung und gute Teamkommunikation. Insbesondere, weil wir die App bhere auf zwei Plattformen (Android und iOS) gleichzeitig aufgebaut haben. Die Tatsache, dass wir uns nicht wie in der WildWeek auf direkten Wege schnell austauschen konnten, machte das Projekt umso lehrreicher, weil es auch nebenbei die heutige Home Office Arbeitsweise gut widerspiegelt hat.<br><br>Persönlich habe ich mich speziell im Bereich der Android App Entwicklung einbringen können. Dort war ich mit einigen Kollegen an der Gestaltung der UI unserer Screens dran. Neben dem Entwicklungs-Part habe ich auch an der Gestaltung unseres App-Logos beigetragen und fürs Marketing die Bierdeckeln designed, welche wir dann als Merch an die Interessent:innen verteilt haben. Ich fand die Tasks sehr abwechslungsreich und konnte mich erstmals tiefgründig mit der Programmiersprache Kotlin auseinandersetzen. Erste wirkliche Programmiererfahrung von Apps hatte ich damals noch mit Java.<br><br>Rückblickend betrachtet bin ich froh gewesen, mit unserem Team eine solch innovative App auf die Beine gestellt zu haben. Die Umsetzung hat gezeigt, dass wir mit vielen guten Ideen und einigem Kreativitätsvermögen, auch technisch herausfordernde Anforderungen meistern können. Nichtsdestotrotz ist zu erwähnen, dass der Weg dorthin nicht immer einfach war. Durch die Parallelentwicklung (Android/iOS) mussten wir ständig so up-to-date sein, dass auf beiden Systemen ein ziemlich einheitliches Design und verhalten aufgebaut werden konnte. Außerdem waren zahlreiche Testläufe nötig, bis wir eine stabile, plattformübergreifende Lösung gefunden hatten, um zwischen allen Endgeräten ein BLE-Mesh aufzubauen, über das die Kommunikation schließlich zuverlässig stattfinden konnte.</p>



<h3 class="wp-block-heading">Felix</h3>



<p>Dieses Gruppen-Semesterprojekt war für mich eine sehr spannende Herausforderung, weil wir in einem großen Team eine komplette App für iOS und Android entwickelt haben und diese dann auch veröffentlicht haben. Im Vergleich zu der Wild Programming Week war es finde ich viel anstrengender, weil wir einfach über einen langen Zeitraum uns immer koordinieren mussten. Aber im Großen und Ganzen hat alles gut funktioniert.</p>



<p>Zum Start haben wir zuerst ein Backend entwickelt für User Anmeldung, was dann aber nicht verwendet wurde, weil wir die App offline verwenden wollten, das war anfangs frustrierend, weil dabei Zeit draufgegangen ist, aber natürlich verständlich. Dann habe ich auch ziemlich am Anfang eine Website entwickelt, die, wie ich finde, sehr gut geworden ist. Ansonsten habe ich im Android Team und beim Merch für die Projekte Vernissage geholfen. Das fand ich am spannendsten, da ich Kotlin besser kennenlernen konnte.</p>



<p>Das gesamte Projekt hat mir sehr gut gefallen, vor allem weil es ein sehr reales und arbeitsnahes Projekt war. Wir waren ein gutes Team und haben gute Meetings abgehalten. Es hat alles gut funktioniert, wenn auch nicht ohne Schwierigkeiten.</p>



<h3 class="wp-block-heading">Caroline</h3>



<p>Im Vergleich zur Extreme Programming Week im 2. Semester hatten wir diesmal mehr Zeit fürs Einarbeiten und Ausprobieren, wobei die Entwicklung einer nativen App auf zwei unterschiedlichen Plattformen dafür neue Herausforderungen mit sich brachte. Ich habe hauptsächlich gemeinsam mit Katharina an der iOS-Version gearbeitet, was im Pair-Programming sehr gut funktioniert hat. Besonders hilfreich war dabei, dass sie bereits mehr Erfahrung mit Swift hatte, wodurch ich mich trotz anfänglicher Unsicherheiten schnell einarbeiten konnte.</p>



<p>Eine der größten Herausforderungen war die Umsetzung der Bluetooth-Low-Energy-Kommunikation. Da es auf iOS im Wesentlichen nur Core Bluetooth gibt, mussten wir viele Teile selbst erarbeiten. Zunächst mussten wir die Grundlagen von BLE verstehen und verschiedene Ansätze ausprobieren, bis wir zu einer funktionierenden Lösung kamen, die über mehrere Geräte hinweg funktioniert. Besonders hilfreich war Davids erste Umsetzung eines Meshs auf Android, auch wenn die Übertragung der Logik auf iOS aufgrund plattformspezifischer Unterschiede nicht einfach war.</p>



<p>Zusätzlich haben wir die iOS-Version der App im App Store veröffentlicht, was für mich eine neue und spannende Erfahrung war. Dabei habe ich einen Einblick in den Release-Prozess sowie die dafür notwendigen Schritte und Anforderungen von Apple bekommen.</p>



<p>Insgesamt hat mir das Projekt nochmal gezeigt, wie wichtig klare Absprachen im Team sowie ein möglichst fertiges und einheitliches Design zu Beginn eines Projekts sind. Fehlende oder unklare Definitionen führen später nämlich zu Mehraufwand und Inkonsistenzen zwischen den Plattformen. Rückblickend war das Projekt jedoch sehr lehrreich und hat mir sowohl technisch als auch im Bereich Teamarbeit wertvolle Erfahrungen gebracht.</p>



<h3 class="wp-block-heading">Sebastian</h3>



<p>Auch wenn wir im zweiten Semester die Wild Programming Week hatten, in welcher wir eine App innerhalb einer Woche entwickeln mussten, war dieses Semesterprojekt doch noch einmal ein ganz neues Erlebnis. Eine App über ein ganzes Semester zu entwickeln hat das Ganze leichter wie auch schwerer gestaltet.&nbsp;</p>



<p>Durch den Zeitrahmen hatten wir um einiges mehr Zeit zu entwickeln, nicht wie in der Wild Week. Aber auch durch diesen größeren Zeitrahmen wurde es schwerer, da es zum einen natürlich den Projektumfang erhöht hat. Gleichzeitig war es auch um einiges schwerer, den nötigen Arbeitsaufwand einzuschätzen, wodurch man zum Beispiel zu Beginn die Arbeitspakete zu klein für einen Sprint geschätzt hat.&nbsp;</p>



<p>Ich war vor allem mit UI Umsetzungen auf Android, zusammen mit der Implementierung der Nutzungserkennung zuständig. Bei der UI Umsetzung der die größte Herausforderung die Abstimmung zwischen Android und iOS. Zwar sind beide Plattformen von der gleichen Basis ausgegangen, auf beiden gab es aber kleiner Änderungen, welche dafür gesorgt haben, dass das Design nicht komplett einstimmig waren und hat extra Arbeit gegen Ende benötigt zum Anpassen.</p>



<p>Im Ganzen war es aber wieder ein gutes Erlebnis, mit einem tollen Team. Das ganze kam mit wichtigen Erfahrungen, wie Programmiersprachen Erlernung, App Store Einrichtungen und auch das erneute zeigen, wie wichtig gute Kommunikation und Abstimmung ist, um extra Arbeit zu vermeiden. Ich wäre jederzeit bereit, noch ein Projekt mit diesem Team zu machen.</p>



<h3 class="wp-block-heading">Jan</h3>



<p>Es war sehr nett, mit allen Studienkollegen der Masterklasse ein Projekt umzusetzen. Spannend war, wie sich jeder mit seinen Stärken eingebracht hat. Gerne hätte ich noch mehr an diesem Projekt gearbeitet und dafür auf andere Lehrveranstaltungen verzichtet.</p>



<p>Das Projekt hat sich im Laufe der Zeit in eine spannende Richtung entwickelt. Features, die wir anfangs eingeplant hatten, haben sich bei genauerer Betrachtung als nicht wichtig oder sogar als störend erwiesen und wurden daher gestrichen. Ich bin beispielsweise sehr froh über die Entscheidung, dass die App zu 100% offline funktioniert und es kein Backend gibt. Das ermöglicht den flexiblen Einsatz der App, zum Beispiel in Kellerlokalen ohne Mobilfunk, und hat den Vorteil, dass User ohne lästige Account-Erstellung direkt loslegen können. Für uns als Team bedeutet der Wegfall eines Backends, dass wir die Applikation kostengünstiger und mit weniger Aufwand betreiben können.</p>



<p>Wir können stolz darauf sein, dass wir eine neuartige und wirklich nützliche Applikation geschaffen haben, die ausreichend stabil läuft. Natürlich sehen wir noch einige offene Themen, die wir gerne angehen würden. Schade, dass wir vorerst kaum Zeit mehr für bHere haben werden, da wir uns nun auf unsere Masterarbeiten konzentrieren müssen.</p>



<h3 class="wp-block-heading">Katharina</h3>



<p>Das Projekt &#8220;bHere&#8221; war für mich eine besonders wertvolle Erfahrung. In meiner Rolle als Projektleiterin übernahm ich die Moderation der Sprint-Meetings, repräsentierte die Gruppe gegenüber unseren Stakeholdern (unseren Masterklassenleitern) und behielt den Gesamtüberblick über Fortschritt und offene Punkte.</p>



<p>Zusätzlich war ich gemeinsam mit Caro für die iOS-Entwicklung verantwortlich. Wir haben intensiv im Pair Programming gearbeitet und unsere Zusammenarbeit war dabei sehr produktiv. Besonders spannend war die Integration der BLE-Funktionalität – dank Davids Vorarbeit konnten wir diese auch erfolgreich in die iOS-App einbinden. Die BLE-Kommunikation auch plattformübergreifend zwischen iOS und Android zum Laufen zu bringen, stellte allerdings eine technische Herausforderung dar, da sich insbesondere das Debugging der Verbindung als nicht so trivial erwies.</p>



<p>Zeitlich war das Semester ebenfalls herausfordernder als gedacht. Im Vergleich zur &#8220;Wild Week&#8221; erforderte dieses Semestergruppenprojekt ein noch höheres Maß an Eigenorganisation und Abstimmung. Gerade gegen Ende kamen viele Aufgaben parallel zusammen, wodurch Priorisierung und Struktur besonders wichtig wurden. Für zukünftige Projekte nehme ich außerdem mit, wie wichtig ein frühzeitig klar definiertes und abgestimmtes Design ist, um plattformübergreifend noch effizienter arbeiten zu können.</p>



<p>Ein besonderes Highlight war für mich die erstmalige App-Einreichung im App Store. Der umfangreiche Einreichungsprozess hat uns auf der Zielgeraden noch einmal intensiv gefordert, ich konnte daraus aber auch sehr viel lernen.</p>



<p>Insgesamt habe ich sehr viel Arbeit und Engagement in dieses Projekt investiert – sowohl in die technische Umsetzung der iOS-App, als auch in die Organisation und Qualitätssicherung des ganzen Projekts. Umso stolzer bin ich auf das entstandene Produkt und auf das, was wir als Team erreicht haben.&nbsp;</p>



<h3 class="wp-block-heading has-medium-font-size">Matthias</h3>



<p>Das Projekt hat mir einen spannenden Einblick gegeben, wie komplex die Entwicklung einer mobilen App werden kann, wenn sie plattformübergreifend funktionieren und gleichzeitig komplett offline nutzbar sein soll. Besonders spannend fand ich es, gemeinsam im Team einen Lösungsansatz für unser Bluetooth-Mesh-System zu suchen. Vor allem, weil es für unseren Anwendungsfall keine bestehende Lösung gab. Ich habe dabei auch versucht, ein eigenes Konzept zu entwickeln. Dieses war zwar noch nicht vollständig ausgereift und hätte mehr Zeit benötigt, hat mir aber geholfen, die technischen Herausforderungen besser zu verstehen und viel von den Lösungsansätzen der anderen im Team zu lernen.</p>



<p>Intensiver beschäftigt habe ich mich mit der Umsetzung der Nutzungserkennung unter iOS. Ziel war es, das Verhalten der App während der Nutzung besser nachvollziehen und entsprechende Daten erfassen zu können. Dabei musste darauf geachtet werden, dass möglichst ähnliche Informationen wie auf Android gesammelt werden, damit die Nutzung plattformübergreifend vergleichbar bleibt. Dadurch konnte ich mich stärker mit dem Verhalten von Apps unter iOS auseinandersetzen und besser verstehen, wie Apps im Hintergrund arbeiten und wie solche Informationen sinnvoll für die Weiterentwicklung eines Produkts genutzt werden können.</p>



<p>Außerdem hatte ich die Möglichkeit, den Prozess rund um die Veröffentlichung der App im Apple App Store aus nächster Nähe mitzuerleben. Es war spannend zu sehen, welche Schritte und Anforderungen notwendig sind, bis eine App tatsächlich eingereicht und veröffentlicht werden kann.</p>



<p>Mit am meisten Spaß haben mir die Diskussionen rund um die User Experience der App gemacht. In den Meetings habe ich gemerkt, dass mich dieser Bereich besonders interessiert und ich mich dort auch am besten einbringen kann. Die Kombination aus technischen Überlegungen und der Frage, wie sich eine App für Nutzer:innen möglichst intuitiv bedienen lässt, fand ich besonders spannend.</p>



<p>Während des Projekts bin ich mit vielen neuen Themen in Berührung gekommen und konnte dabei viel lernen, sowohl technisch als auch in der Zusammenarbeit im Team. Gleichzeitig war die Arbeit durch die vielen gemeinsamen Lösungsansätze sehr motivierend, wodurch das Lernen fast nebenbei passiert ist.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/studium/studium-projekte/blog-bhere-not-on-your-phone/">Projekt | bHere &#8211; not on your phone</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		<enclosure url="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/NFC-Solomodus.mp4" length="3462174" type="video/mp4" />

			</item>
		<item>
		<title>Workshop &#124; Astro</title>
		<link>https://mobile.fhstp.ac.at/workshop/workshop-astro/</link>
		
		<dc:creator><![CDATA[Caroline Labres]]></dc:creator>
		<pubDate>Sun, 16 Nov 2025 17:20:52 +0000</pubDate>
				<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[Workshop]]></category>
		<category><![CDATA[Astro]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15111</guid>

					<description><![CDATA[<p>Im 3. Semester habe ich einen Workshop zu Astro gehalten. Dabei habe ich erklärt, was das Webframework ausmacht, und anhand von einem praktischen Beispiel die wichtigsten Kernfunktionen demonstriert. Was ist Astro? Astro ist ein Framework für contentfokussierte Webprojekte, wie z.B. Blogs, E-Commerce- oder Marketing-Websites. Es setzt auf eine komponentenbasierte Web-Architektur, was bedeutet, dass das meiste <a class="read-more" href="https://mobile.fhstp.ac.at/workshop/workshop-astro/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/workshop/workshop-astro/">Workshop | Astro</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Im 3. Semester habe ich einen Workshop zu Astro gehalten. Dabei habe ich erklärt, was das Webframework ausmacht, und anhand von einem praktischen Beispiel die wichtigsten Kernfunktionen demonstriert.</p>



<h2 class="wp-block-heading">Was ist Astro?</h2>



<p>Astro ist ein Framework für contentfokussierte Webprojekte, wie z.B. Blogs, E-Commerce- oder Marketing-Websites. Es setzt auf eine <strong>komponentenbasierte Web-Architektur</strong>, was bedeutet, dass das meiste als statische HTML-Seite gerendert wird und man kleine Islands mit JavaScript für Interaktivität hinzufügen kann. Astro verfolgt einen <strong>Server-first-Ansatz</strong> und kommt standardmäßig <strong>ohne JavaScript</strong> am Client aus, liefert aber bei Bedarf <strong>Unterstützung für Frameworks</strong> wie React, Vue, Svelte, Solid etc. Darüber hinaus bietet Astro <strong>Content Collections</strong>, mit denen sich Markdown-Inhalte strukturiert organisieren und mithilfe von TypeScript typsicher validieren lassen.</p>



<h2 class="wp-block-heading">Projekt erstellen</h2>



<p><code>npm create astro@latest</code> (basic, helpful starter Projekt auswählen)</p>



<p>In VS Code gibt es eine Extension namens Astro, die hilfreich ist.</p>



<p> Ordnerstruktur (als Beispiel):</p>



<ul class="wp-block-list">
<li>assets</li>



<li>components</li>



<li>content (für Content Collections)</li>



<li>layouts</li>



<li>pages (file-based Routing)</li>



<li>styles</li>
</ul>



<h2 class="wp-block-heading">Dateiaufbau und Astro-Komponenten</h2>



<ul class="wp-block-list">
<li>Dateiendung: .astro</li>



<li>Codeausführung:
<ul class="wp-block-list">
<li>serverseitig: <code>--- ---</code> (Frontmatter)</li>



<li>clientseitig: <code>&lt;script>&lt;/script></code></li>
</ul>
</li>



<li>JSX-ähnliche Ausdrücke
<ul class="wp-block-list">
<li><code>{variable}</code> in HTML</li>



<li>Aber: Funktionen und Objekte können so nicht übergeben werden (wie z.B. bei React), stattdessen mit Script-Tag umsetzbar</li>
</ul>
</li>
</ul>



<p>Beispielsweise MyAstroComp.astro:</p>



<pre class="wp-block-code"><code>---
// Script mit JS, das am Server ausgeführt wird
const text = "Hello World";
---
&lt;!-- Hier Template der Komponente mit HTML, CSS und JS --&gt;
&lt;div&gt;{text}&lt;/div&gt;</code></pre>



<p>Was nicht funktioniert:</p>



<pre class="wp-block-code"><code>---
function handleClick() {
  console.log("clicked");
}
---
&lt;button onclick="handleClick()"&gt;{text}&lt;/button&gt;</code></pre>



<p>Komponente in index.astro verwenden:</p>



<pre class="wp-block-code"><code>---
import MyAstroComp from "../components/MyAstroComp.astro";
---
&lt;MyAstroComp /&gt;</code></pre>



<ul class="wp-block-list">
<li><code>&lt;slot /></code> für Children (wie {children} in React)</li>



<li>Mit <code>Astro.props</code> auf Properties zugreifen</li>
</ul>



<pre class="wp-block-code"><code>---
interface Props {
  name: string;
}
const { name } = Astro.props;
---
&lt;h2&gt;Hello {name}!&lt;/h2&gt;</code></pre>



<h2 class="wp-block-heading">Unterschiede Astro vs. JSX</h2>



<figure class="wp-block-table"><table class="has-black-color has-text-color has-link-color has-fixed-layout"><thead><tr><th></th><th>Astro</th><th>JSX</th></tr></thead><tbody><tr><td>Attribute</td><td>kebab-case</td><td>camelCase</td></tr><tr><td>Mehrere Elemente</td><td>Ohne Parent zulässig</td><td>Nur in einem einzelnen &lt;div&gt; oder &lt;&gt; zulässig</td></tr><tr><td>Kommentare</td><td>HTML- und JS-Kommentare</td><td>JS-Kommentare</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">React hinzufügen</h2>



<p>Interaktivität in Astro Komponenten einzubauen ist mühsam. Um mit einem Buttonklick umgehen zu können, müsste man ein &lt;script&gt; Tag hinzufügen. Stattdessen kann man aber auch ein beliebiges anderes Framework zum Projekt hinzufügen und so auch beispielsweise React-Komponenten bauen und nutzen.</p>



<p>Um React als Beispiel hinzuzufügen: <code>npx astro add react</code></p>



<p>Achtung: Komponente wird by default nur am Server gerendert!</p>



<p>Für Interaktivität braucht es Hydration und eine Client Directive.</p>



<h3 class="wp-block-heading">Client Directives</h3>



<p>Die client:* Directive gibt an, wann das JavaScript an den Browser geschickt werden soll. Die Komponente wird zuerst am Server gerendert (außer bei client:only), dann wird das JS gesendet und somit wird die Komponte hydrated und interaktiv.</p>



<ul class="wp-block-list">
<li><code>client: load</code>
<ul class="wp-block-list">
<li>JS: sofort beim Laden der Seite</li>
</ul>
</li>



<li><code>client: idle</code>
<ul class="wp-block-list">
<li>JS: nach initialem Ladeprozess und wenn requestIdleCallback-Event ausgelöst wird</li>
</ul>
</li>



<li><code>client: visible / client:visible={{rootMargin}}</code>
<ul class="wp-block-list">
<li>JS: sobald Komponente bzw. angegebener Margin sichtbar ist</li>
</ul>
</li>



<li><code>client:media={string}</code>
<ul class="wp-block-list">
<li>JS: wenn CSS media query erfüllt wird (z.B. nur für bestimmte Bildschirmgrößen)</li>
</ul>
</li>



<li><code>client:only={string}</code>
<ul class="wp-block-list">
<li>Überspringt SSR und rendert Komponente nur am Client. Framework muss als String übergeben werden.</li>
</ul>
</li>
</ul>



<p>Die Client Directive wird dort hinzufügt, wo die Komponente verwendet wird.</p>



<pre class="wp-block-code"><code>---
import MyReactButton from "../components/MyReactButton";
---
&lt;MyReactButton client:load /&gt;</code></pre>



<h2 class="wp-block-heading">Output Type für Build</h2>



<p>In der astro.config Datei kann der Output Type festgelegt werden. Dieser bestimmt, wann die Seiten standardmäßig gerendert werden (beim Builden oder on demand). Das gilt für alle Seiten, außer bei denen eine Ausnahme festgelegt ist.</p>



<p>In astro.config.mjs: <code>output: 'static'</code> oder <code>'server'</code></p>



<ul class="wp-block-list">
<li><code>static</code> (default): SSG, Seiten werden vorgerendert (<em>prerendered</em>); Ergebnis: statische Website</li>



<li><code>server</code>: SSR, Seiten werden on demand gerendert; Ergebnis: server-rendered Website</li>



<li>Für einzelne Seite ändern: <code>export const prerender = false</code>
<ul class="wp-block-list">
<li>wenn in config static: <code>false</code></li>



<li>wenn in config server: <code>true</code></li>
</ul>
</li>
</ul>



<p>Wichtig: Wenn eine Seite SSR verwendet, muss ein <strong>Server-Adapter</strong> (z.B. node) festgelegt werden: <code>npx astro add node</code></p>



<h2 class="wp-block-heading">Blog als Praxisbeispiel</h2>



<p>Als Beispiel wird ein kleiner, einfacher Blog programmiert. Dieser beinhaltet zwei Seiten, wobei auf einer alle Einträge mit Bild, Datum und Titel aufgelistet werden (Übersichtsseite) und auf der anderen die Informationen des jeweiligen Eintrags stehen (Detailseite). Die einzelnen Blogbeiträge sollen in Form von Markdown-Dateien erstellt, bearbeitet und verwaltet werden können. Auf das Styling wird bei diesem Beispiel nicht eingegangen.</p>



<h3 class="wp-block-heading">Content Collection erstellen</h3>



<p>Content Collections helfen dabei, Markdown-Dateien zu organisieren. Genau das wird für die Blogbeiträge benötigt. Um eine Collection zu erstellen, muss diese in src/content.config.ts definiert werden.</p>



<pre class="wp-block-code"><code>import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";

const blog = defineCollection({
  loader: glob({ base: "./src/content/blog", pattern: "**/*.{md,mdx}" }),
  schema: () =&gt;
    z.object({
      title: z.string(),
      date: z.coerce.date(),
      img: z.string(),
    }),
});

export const collections = { blog };</code></pre>



<p>Die Funktion <code>defineCollection()</code> verlangt dabei zwei Parameter, einerseits den Loader und andererseits optional das Schema. Der Loader legt fest, wie und von wo die Inhalte der Collection geladen werden. Astro stellt dabei zwei integrierte Varianten zur Verfügung:</p>



<ul class="wp-block-list">
<li><code>glob()</code>: erstellt Einträge aus Ordnern mit Dateien</li>



<li><code>file()</code>: erstellt Einträge basierend auf einer lokalen Datei (z.B. JSON-File)</li>
</ul>



<p>Das Schema wird mit zod erstellt. Wird ein Schema definiert, so werden die entsprechenden Markdown-Dateien dahingehend validiert. Außerdem können generierte Types verwendet werden (z.B. <code>type Props = CollectionEntry&lt;"blog"&gt;["data"];</code>). Wichtig ist nur, dass der Dev-Server neu gestartet wird, wenn sich Änderungen am Schema ergeben, sodass Astro das mitbekommt.</p>



<p>Ein Blogeintrag soll in diesem Fall immer einen Titel, ein Datum und ein Bild beinhalten, sodass diese Informationen auf der Übersichtsseite angezeigt und auf der Detailseite immer gleich formatiert werden können.</p>



<h3 class="wp-block-heading">Blogbeiträge hinzufügen</h3>



<p>Es können jetzt diverse Blogbeiträge in Form von Markdown-Dateien unter content/blog erstellt werden (Pfad in content.config.ts festgelegt).</p>



<p>Beispiel: first-entry.md</p>



<pre class="wp-block-code"><code>---
title: "First Entry"
date: "2025-10-30"
img: "/favicon.svg"
---
Hello, this is my first entry.

## H2

This is a paragraph.</code></pre>



<p>Im Frontmatter (innerhalb der drei Bindestriche) werden die drei Parameter angegeben, darunter folgt der Inhalt. Als Bild wird der Einfachheit halber das favicon im public-Ordner hergenommen. Der Blogbeitrag kann Überschriften, Absätze, Links, Codeteile, Tabellen und alles, was Markdown zu bieten hat, beinhalten. Wichtig ist nur, dass man das entsprechende Styling dafür definiert (h2, p, code, a etc.).</p>



<h4 class="wp-block-heading">MDX</h4>



<p>Es können nicht nur md-Dateien erstellt werden, sondern auch mdx-Dateien, in denen die eigenen Komponenten (egal ob Astro, React etc.) verwendet werden können. Es muss nur die entsprechende Astro-Integration installiert werden (<code>npx astro add mdx</code>) und mdx in der Definition der Content Collection berücksichtigt werden (wurde bereits getan).</p>



<p>Beispiel: second-entry.mdx</p>



<pre class="wp-block-code"><code>---
title: "Second Entry"
date: "2025-10-31"
img: "/favicon.svg"
---

This is my second entry.

import MyReactButton from "../../components/MyReactButton"

&lt;MyReactButton client:load /&gt;</code></pre>



<p>components/MyReactButton.tsx</p>



<pre class="wp-block-code"><code>export default function MyReactButton(){

    function handleClick(){
        console.log("Hello, you clicked me")
    }

    return (
        &lt;button onClick={handleClick}&gt;Click me&lt;/button&gt;
    )
}</code></pre>



<h3 class="wp-block-heading">Seiten erstellen</h3>



<p>Astro verwendet file-based Routing. Die Ordner- und Dateistruktur im pages-Ordner bestimmt somit automatisch, unter welchen URLs die Seiten aufgerufen werden können. Im pages-Ordner wird ein Unterordner blog und darin index.astro und [slug].astro angelegt. Der Blog ist somit unter /blog erreichbar. index.astro ist eine statische Route, während [slug].astro eine dynamische Route ist. Der Parameter slug kann dabei durch eine beliebige andere Bezeichnung ersetzt werden. Für mehr Tiefe kann auch ein Rest-Parameter verwendet werden: [&#8230;path].astro. </p>



<h4 class="wp-block-heading">Übersichtsseite</h4>



<p>Für die index Seite wird zuerst ein Layout erstellt. Ein Layout ist dabei nichts anderes als eine normale Astro-Komponente.</p>



<p>layouts/Layout.astro</p>



<pre class="wp-block-code"><code>---<br>import "../styles/global.css";<br>---<br><br>&lt;!doctype html&gt;<br>&lt;html lang="en"&gt;<br>  &lt;head&gt;<br>    &lt;meta charset="UTF-8" /&gt;<br>    &lt;meta name="viewport" content="width=device-width" /&gt;<br>    &lt;link rel="icon" type="image/svg+xml" href="/favicon.svg" /&gt;<br>    &lt;meta name="generator" content={Astro.generator} /&gt;<br>    &lt;title&gt;My Blog&lt;/title&gt;<br>  &lt;/head&gt;<br>  &lt;body&gt;<br>    &lt;slot /&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;<br><br>&lt;style&gt;<br>  html,<br>  body {<br>    margin: 0;<br>    width: 100%;<br>    height: 100%;<br>  }<br>&lt;/style&gt;</code></pre>



<p>Für den Header kann ebenso eine Astro-Komponente erstellt werden (components/Header.tsx).</p>



<pre class="wp-block-code"><code>&lt;header&gt;
  &lt;nav&gt;
    &lt;a href="/blog"&gt;My Blog&lt;/a&gt;
  &lt;/nav&gt;
&lt;/header&gt;
</code></pre>



<p>Nun kann index.astro befüllt werden:</p>



<pre class="wp-block-code"><code>---
import { getCollection } from "astro:content";
import Header from "../../components/Header.astro";
import Layout from "../../layouts/Layout.astro";

const posts = (await getCollection("blog")).sort((a, b) =&gt; {
  return b.data.date.valueOf() - a.data.date.valueOf();
});
---

&lt;Layout&gt;
  &lt;Header /&gt;
  &lt;ul&gt;
    {
      posts.map((post) =&gt; (
        &lt;li&gt;
          &lt;a href={"/blog/" + post.id}&gt;
            &lt;div&gt;
              &lt;img src={post.data.img} /&gt;
            &lt;/div&gt;
            &lt;div&gt;{post.data.title}&lt;/div&gt;
            &lt;div&gt;{post.data.date.toLocaleDateString()}&lt;/div&gt;
          &lt;/a&gt;
        &lt;/li&gt;
      ))
    }
  &lt;/ul&gt;
&lt;/Layout&gt;</code></pre>



<p>Mithilfe von <code>getCollection()</code> kann eine Collection, sprich ein Array von Einträgen, geholt werden. In diesem Beispiel werden die Einträge von der Blog-Collection zusätzlich nach dem Datum sortiert.</p>



<h4 class="wp-block-heading">Detailseite</h4>



<p>Für die Detailseite wird ebenso ein Layout erstellt, das den Titel, das Bild und das Datum übergeben bekommt und anzeigt.</p>



<p>layouts/BlogLayout.astro</p>



<pre class="wp-block-code"><code>---
import type { CollectionEntry } from "astro:content";
import Header from "../components/Header.astro";

type Props = CollectionEntry&lt;"blog"&gt;&#91;"data"];

const { title, date, img} = Astro.props;
---

&lt;!doctype html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta name="viewport" content="width=device-width" /&gt;
    &lt;link rel="icon" type="image/svg+xml" href="/favicon.svg" /&gt;
    &lt;meta name="generator" content={Astro.generator} /&gt;
    &lt;title&gt;My Blog&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;Header /&gt;
    &lt;main&gt;
      &lt;article&gt;
        &lt;div&gt;
          &lt;img src={img} /&gt;
        &lt;/div&gt;
        &lt;div&gt;{date.toLocaleDateString()}&lt;/div&gt;
        &lt;h1&gt;{title}&lt;/h1&gt;
        &lt;div&gt;
          &lt;slot /&gt;
        &lt;/div&gt;
      &lt;/article&gt;
    &lt;/main&gt;
  &lt;/body&gt;
&lt;/html&gt;

&lt;style&gt;
  html,
  body {
    margin: 0;
    width: 100%;
    height: 100%;
  }
&lt;/style&gt;</code></pre>



<p>Die Detailseite muss nun den Parameter slug auslesen und die entsprechenden Informationen dem BlogLayout übergeben. Es gibt zwei Varianten, das zu tun, je nachdem ob man SSR oder SSG verwenden möchte.</p>



<p><strong>Variante 1: SSR (on demand Rendering)</strong></p>



<pre class="wp-block-code"><code>---
import { render } from "astro:content";
import { getEntry } from "astro:content";
import BlogLayout from "../../layouts/BlogLayout.astro";

export const prerender = false;
const { slug } = Astro.params;

if (!slug) {
  return Astro.rewrite("/404");
}

const entry = await getEntry("blog", slug);

if (!entry) {
  return Astro.rewrite("/404");
}

const { Content } = await render(entry);
---

&lt;BlogLayout {...entry.data}&gt;
  &lt;Content /&gt;
&lt;/BlogLayout&gt;
</code></pre>



<p>Mithilfe von <code>Astro.params</code> kann der Parameter slug ausgelesen werden. Mit <code>getEntry()</code> wird dann der entsprechende Eintrag geholt. Wenn es keinen passenden Eintrag gibt, wird 404 angezeigt. Um den Inhalt der Zielseite anzuzeigen, ohne die URL zu verändern, wird <code>Astro.rewrite()</code> genutzt.</p>



<p><strong>Variante 2: SSG (statische Seite)</strong></p>



<pre class="wp-block-code"><code>---
import type { GetStaticPaths } from "astro";
import { render } from "astro:content";
import BlogLayout from "../../layouts/BlogLayout.astro";
import { getCollection } from "astro:content";

export const getStaticPaths = (async () =&gt; {
  const entries = await getCollection("blog");

  return entries.map((entry) =&gt; ({
    params: { slug: entry.id },
    props: entry,
  }));
}) satisfies GetStaticPaths;

const entry = Astro.props;

const { Content } = await render(entry);
---

&lt;BlogLayout {...entry.data}&gt;
  &lt;Content /&gt;
&lt;/BlogLayout&gt;
</code></pre>



<p>Soll eine dynamische Route statisch sein, so muss sie eine Funktion namens <code>getStaticPaths()</code> exportieren, die ein Array an Objekten mit dem property <code>params</code> zurückgibt. So werden alle möglichen Paths vordefiniert. In diesem Beispiel holt man sich also alle Einträge der Blog-Collection in der <code>getStaticPaths()</code>-Funktion und über die Properties (<code>Astro.props</code>) können dann die Informationen des einzelnen Eintrags ausgelesen werden.</p>



<h2 class="wp-block-heading">Fazit</h2>



<p>Mit Astro können schnelle Websites erstellt werden. Wenn man bereits Erfahrung mit HTML, JSX oder React hat, so fällt einem der Einstieg in das Framework besonders leicht, da man viele vertraute Konzepte wiederfindet. Nur bei komplexeren Websites stößt Astro irgendwann auf seine Grenzen.</p>



<h2 class="wp-block-heading">Quelle</h2>



<p><a href="https://docs.astro.build/en">https://docs.astro.build/en</a></p>



<p></p>
<p>The post <a href="https://mobile.fhstp.ac.at/workshop/workshop-astro/">Workshop | Astro</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PrintToMobile &#124; TreeFund</title>
		<link>https://mobile.fhstp.ac.at/development/printtomobile-treefund/</link>
		
		<dc:creator><![CDATA[Sander Hahn]]></dc:creator>
		<pubDate>Fri, 17 Oct 2025 12:56:35 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[Print-to-mobile]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=14942</guid>

					<description><![CDATA[<p>Today’s world is becoming increasingly complicated – and increasingly grey. Pollution, conflict, and overconsumption are draining the color from our planet. The idea of TreeFund is simple: find an easy, meaningful way to help make our world greener again – one small step at a time. Idea The goal of TreeFund is to provide an <a class="read-more" href="https://mobile.fhstp.ac.at/development/printtomobile-treefund/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/printtomobile-treefund/">PrintToMobile | TreeFund</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Today’s world is becoming increasingly complicated – and increasingly grey. Pollution, conflict, and overconsumption are draining the color from our planet. The idea of TreeFund is simple: find an easy, meaningful way to help make our world greener again – one small step at a time.</p>



<h2 class="wp-block-heading">Idea</h2>



<p>The goal of <em>TreeFund</em> is to provide an easy and transparent way for people to contribute to environmental restoration projects in St. Pölten. Its main focus is supporting tree planting initiatives and teaching new generations how to help our planet. The idea is to connect with individuals who want to make a difference and focus on their specific needs. People will first encounter <em>TreeFund </em>through posters and flyers placed around the city. A QR code on each will lead directly to the <em>TreeFund </em>website, where users can learn more, get involved, and track the impact of their contributions.</p>



<p></p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="595" height="842" data-id="14964" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Print2-5.jpg" alt="" class="wp-image-14964"/></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="720" height="1520" data-id="14963" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-134357_Camera-5.jpg" alt="" class="wp-image-14963"/></figure>
</figure>
</div>
</div>



<p></p>



<h2 class="wp-block-heading"><strong>Implementation</strong></h2>



<p>As the first step in the implementation process, I created a user persona: <em>Lisa Gruber</em>, a student at the <em>University of Applied Sciences St. Pölten</em>.</p>



<p><em>Lisa </em>is deeply environmentally conscious and eager to contribute to positive change. However, she often feels frustrated by the impersonal nature of many existing donation platforms. She wants to see the real impact of her actions and connect with initiatives that align with her values on a local level.</p>



<p></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1787" height="1725" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Persona.png" alt="" class="wp-image-14966" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Persona.png 1787w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Persona-1536x1483.png 1536w" sizes="auto, (max-width: 1787px) 100vw, 1787px" /></figure>



<p></p>



<p>To personalize this process, the user (Lisa) first contacts TreeFund via a form describing their personal needs and where they want to see a part of the world a little greener. Only after the user is happy and the tree planting effort is accepted by the city, the payment process begins.&nbsp;</p>



<p>To attract younger customers the design follows a minimalist aesthetic with clean whites and greens to emphasize the simplicity and positivity of the project’s goal. The design was first created in Figma with inspirations like Ecosia and TreeApp. My goal was to stick to a strict number of TailwindCSS colors. The website switches between Stone-50 and -100 for the background and Lime-400, -500, -600 and -800 for the green accents.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="387" height="144" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Frame-17.png" alt="" class="wp-image-14982"/></figure></div>


<p></p>



<p>After the design process, the actual website was implemented using React, Next.js, Tailwind CSS, and Lucide for icons.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1436" height="2724" data-id="14975" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135253_Chrome-1.jpg" alt="" class="wp-image-14975" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135253_Chrome-1.jpg 1436w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135253_Chrome-1-810x1536.jpg 810w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135253_Chrome-1-1080x2048.jpg 1080w" sizes="auto, (max-width: 1436px) 100vw, 1436px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1440" height="2724" data-id="14976" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135326_Chrome-1.jpg" alt="" class="wp-image-14976" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135326_Chrome-1.jpg 1440w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135326_Chrome-1-812x1536.jpg 812w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135326_Chrome-1-1083x2048.jpg 1083w" sizes="auto, (max-width: 1440px) 100vw, 1440px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1440" height="2920" data-id="14974" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135332_Chrome.jpg" alt="" class="wp-image-14974" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135332_Chrome.jpg 1440w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135332_Chrome-757x1536.jpg 757w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251017-135332_Chrome-1010x2048.jpg 1010w" sizes="auto, (max-width: 1440px) 100vw, 1440px" /></figure>
</figure>



<p><strong>Link to the Web Application:</strong> https://fhstp-print2mobil.vercel.app/</p>



<p><br><strong>Disclaimer: </strong><em>This is a personal project created for educational and illustrative purposes. It is not affiliated with any existing environmental organizations. The aim is to demonstrate how web technology can be used to promote sustainability and environmental awareness.</em></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/printtomobile-treefund/">PrintToMobile | TreeFund</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Print2Mobile &#124; AR &#8211; Web Application to project 3D Objects onto a Catalog</title>
		<link>https://mobile.fhstp.ac.at/development/webdevelopment/print2mobile-ar-web-application-to-project-3d-objects-onto-a-catalog/</link>
		
		<dc:creator><![CDATA[Jakob Laschober]]></dc:creator>
		<pubDate>Thu, 16 Oct 2025 12:43:41 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[AR]]></category>
		<category><![CDATA[Augmented Reality]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mobile web]]></category>
		<category><![CDATA[Print-to-mobile]]></category>
		<category><![CDATA[Print2Mobile]]></category>
		<category><![CDATA[webdevelopment]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=14874</guid>

					<description><![CDATA[<p>Have you ever seen a cool piece of furniture in a furniture store catalog? Maybe you wondered how the couch looks from behind, or how to view the table in 3D to better estimate its dimensions. Idea I tried to use the well-known store IKEA and its Catalog to implement my idea. This project aims <a class="read-more" href="https://mobile.fhstp.ac.at/development/webdevelopment/print2mobile-ar-web-application-to-project-3d-objects-onto-a-catalog/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/webdevelopment/print2mobile-ar-web-application-to-project-3d-objects-onto-a-catalog/">Print2Mobile | AR &#8211; Web Application to project 3D Objects onto a Catalog</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Have you ever seen a cool piece of furniture in a furniture store catalog? Maybe you wondered how the couch looks from behind, or how to view the table in 3D to better estimate its dimensions.</p>



<p class="has-medium-font-size"><strong>Idea</strong></p>



<p>I tried to use the well-known store IKEA and its Catalog to implement my idea. This project aims to bridge the gap between physical catalogs and digital visualization. The core concept involves using QR codes placed on the product pages to link to an external web application. Once the user scans the code, this application can display a 3D model of the product above its corresponding picture in the physical catalog.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full is-resized is-style-default"><img loading="lazy" decoding="async" width="4080" height="3072" data-id="14937" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/PXL_20251016_083759829-3.jpg" alt="" class="wp-image-14937" style="width:519px;height:auto" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/PXL_20251016_083759829-3.jpg 4080w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/PXL_20251016_083759829-3-1536x1157.jpg 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/PXL_20251016_083759829-3-2048x1542.jpg 2048w" sizes="auto, (max-width: 4080px) 100vw, 4080px" /></figure>



<figure class="wp-block-image size-full is-resized is-style-default"><img loading="lazy" decoding="async" width="960" height="2142" data-id="14932" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103642.jpg" alt="" class="wp-image-14932" style="width:221px;height:auto" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103642.jpg 960w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103642-688x1536.jpg 688w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103642-918x2048.jpg 918w" sizes="auto, (max-width: 960px) 100vw, 960px" /></figure>
</figure>



<p class="has-medium-font-size"><strong>Implementation</strong></p>



<p>For technologies, I used HTML, CSS and JavaScript. For the purpose of pattern recognition and tracking, I used the framework <a href="https://hiukim.github.io/mind-ar-js-doc/">mindAR.js</a>. For displaying the 3D Objects, I used the framework <a href="https://aframe.io/">A-Frame</a>. Sadly, the 3D objects that I used are very high fidelity and that impacts the performance of the application. So when you want to scan the furniture elements on the page, you have to be very careful, not to move too much or too quickly. It&#8217;s hosted on my own server as a docker instance using a Nginx web server.</p>



<figure class="wp-block-gallery has-nested-images columns-3 is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full is-resized"><img decoding="async" data-id="14910" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103732.jpg" alt="" class="wp-image-14910" style="width:306px;height:auto"/></figure>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="960" height="2142" data-id="14928" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103711-1.png" alt="" class="wp-image-14928" style="width:305px;height:auto" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103711-1.png 960w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103711-1-688x1536.png 688w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103711-1-918x2048.png 918w" sizes="auto, (max-width: 960px) 100vw, 960px" /></figure>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="960" height="2142" data-id="14929" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103739.jpg" alt="" class="wp-image-14929" style="width:321px;height:auto" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103739.jpg 960w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103739-688x1536.jpg 688w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Screenshot_20251016-103739-918x2048.jpg 918w" sizes="auto, (max-width: 960px) 100vw, 960px" /></figure>
</figure>



<p>Link to the Webapplication: <a href="https://ikea-scanner.laschober.eu/">https://.ikea-scanner.laschober.eu</a></p>



<p><strong>Disclaimer:</strong> This project is <strong>not affiliated with, endorsed by, or in any way officially connected with IKEA</strong>. The use of IKEA&#8217;s name and catalog images is solely for illustrative purposes as a practical example for the proof of concept.</p>



<p></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/webdevelopment/print2mobile-ar-web-application-to-project-3d-objects-onto-a-catalog/">Print2Mobile | AR &#8211; Web Application to project 3D Objects onto a Catalog</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Print2Mobile &#124; Dishcovery</title>
		<link>https://mobile.fhstp.ac.at/studium/print2mobile-dishcovery/</link>
		
		<dc:creator><![CDATA[Kevin Kraushofer]]></dc:creator>
		<pubDate>Thu, 16 Oct 2025 10:31:34 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=14879</guid>

					<description><![CDATA[<p>(QR Codes in the pictures have no functionality) We’ve all been there, standing in front of the fridge or in the supermarket aisle not knowing what to cook. Meanwhile, tons of perfectly good food end up in the trash every day. Dishcovery aims to change that.With a simple scan at your local supermarket or your <a class="read-more" href="https://mobile.fhstp.ac.at/studium/print2mobile-dishcovery/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/studium/print2mobile-dishcovery/">Print2Mobile | Dishcovery</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p style="font-size:9px">(QR Codes in the pictures have no functionality)</p>



<p>We’ve all been there, standing in front of the fridge or in the supermarket aisle not knowing what to cook. Meanwhile, tons of perfectly good food end up in the trash every day.</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-ad2f72ca wp-block-group-is-layout-flex">
<p><strong>Dishcovery</strong> aims to change that.<br>With a simple scan at your local supermarket or your advertising in the letterbox, the app instantly shows you recipes that match your preferences <em>and</em> the store’s current stock including products nearing their expiry date. But that’s not all: you can also add ingredients you already have at home, and Dishcovery will automatically include them in the recipe suggestions. Every recipe comes with clear quantities, can be saved to your favorites and added directly to a digital shopping list. The app also shows how many products you’ve helped rescue, turning sustainability into something measurable and rewarding.</p>
</div>



<p></p>



<figure class="wp-block-gallery has-nested-images columns-4 is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="393" height="852" data-id="14898" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Homepage-1.png" alt="figma prototype Homepage recipe" class="wp-image-14898"/></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="393" height="852" data-id="14899" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/homepage2.png" alt="figma prototype Homepage ingredients" class="wp-image-14899"/></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="393" height="852" data-id="14897" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Filter.png" alt="figma prototype filterpage overview" class="wp-image-14897"/></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="393" height="852" data-id="14896" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/Filter2.png" alt="figma prototype filterpage whats in your kitchen page." class="wp-image-14896"/></figure>
</figure>



<p></p>



<p>Dishcovery not only inspires creativity in the kitchen — it makes sustainability simple, digital, and rewarding.</p>



<p></p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="840" height="1188" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/website-mit-fake-qr-code-1-1.jpg" alt="" class="wp-image-14919" style="width:376px;height:auto"/></figure></div>


<p><strong>This project is not affiliated with BILLA or the REWE Group in any way. It is a purely academic student project, created for educational purposes only. No financial support, sponsorship, or compensation has been received from BILLA or any other company. Any use of names or logos is solely for demonstration purposes within the prototype.</strong></p>



<p>iPhone design by Luis Orea<br>Icons designed by Kryston Schwarze https://coolicons.cool/<br>Illustrations/Icons designed by Freepick www.freepik.com</p>
<p>The post <a href="https://mobile.fhstp.ac.at/studium/print2mobile-dishcovery/">Print2Mobile | Dishcovery</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Projekt &#124; Powda Club-Dashboard</title>
		<link>https://mobile.fhstp.ac.at/development/projekt-powda-club-dashboard/</link>
		
		<dc:creator><![CDATA[David Grünberger]]></dc:creator>
		<pubDate>Thu, 16 Oct 2025 01:25:15 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Dokumentation]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[clerk]]></category>
		<category><![CDATA[convex]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[Semesterprojekt]]></category>
		<category><![CDATA[shadcn]]></category>
		<category><![CDATA[stripe]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[webhooks]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=14812</guid>

					<description><![CDATA[<p>Im Rahmen des Semesterprojekts im zweiten Semester der Masterklasse Mobile habe ich ein Club Dashboard entwickelt – eine Webanwendung, mit der Skiclubs ihre Ausfahrten verwalten und Teilnehmer:innen direkt online buchen und bezahlen lassen können.Ziel des Projekts war es, einen funktionsfähigen MVP (Minimum Viable Product) zu erstellen, der eine vollständige End-to-End-Integration für Zahlungen bietet – von <a class="read-more" href="https://mobile.fhstp.ac.at/development/projekt-powda-club-dashboard/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/projekt-powda-club-dashboard/">Projekt | Powda Club-Dashboard</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Im Rahmen des Semesterprojekts im zweiten Semester der Masterklasse Mobile habe ich ein <strong>Club Dashboard</strong> entwickelt – eine Webanwendung, mit der Skiclubs ihre <strong>Ausfahrten verwalten</strong> und <strong>Teilnehmer:innen direkt online buchen und bezahlen</strong> lassen können.<br>Ziel des Projekts war es, einen <strong>funktionsfähigen MVP (Minimum Viable Product)</strong> zu erstellen, der eine vollständige End-to-End-Integration für Zahlungen bietet – von der Erstellung der Events bis zur erfolgreichen Bezahlung über die Website.</p>



<p>In diesem Beitrag möchte ich den Aufbau der Anwendung, die verwendeten Technologien sowie einige Herausforderungen und Learnings während der Umsetzung vorstellen.</p>



<h2 class="wp-block-heading">Technologie-Stack</h2>



<p>Das Club Dashboard wurde als moderne Webanwendung mit Fokus auf Skalierbarkeit, Sicherheit und einfache Erweiterbarkeit entwickelt.<br>Hier ein Überblick über die zentralen Technologien:</p>



<h3 class="wp-block-heading">Framework: Next.js (App Router)</h3>



<p>Für das Frontend kam <strong>Next.js</strong> mit dem neuen <strong>App Router</strong> zum Einsatz. Diese Architektur erlaubt serverseitiges Rendering (SSR), API-Routen und eine saubere Trennung von Client- und Server-Komponenten. Dadurch konnte ich sowohl UI-Logik als auch Backend-Funktionalität innerhalb eines Frameworks umsetzen.</p>



<p><strong>Vorteile:</strong></p>



<ul class="wp-block-list">
<li>Serverseitiges Rendering für bessere Performance und SEO</li>



<li>Integrierte API-Routen für serverseitige Logik (z. B. Payment Handling)</li>



<li>Moderne Struktur durch den App Router</li>
</ul>



<h3 class="wp-block-heading">Data Layer: Convex</h3>



<p>Anstatt einer klassischen REST- oder GraphQL-API habe ich mich für <strong>Convex</strong> entschieden – eine innovative Backend-as-a-Service-Lösung, die reaktive Datenabfragen, serverseitige Funktionen und Auth-Integration out of the box bietet.</p>



<p><strong>Convex</strong> ermöglicht es, Daten- und Serverlogik in TypeScript zu schreiben und nahtlos mit dem Frontend zu verbinden. Dadurch entfällt ein Großteil der sonst notwendigen API- und Datenbankkonfiguration.</p>



<h3 class="wp-block-heading">Styling &amp; UI: TailwindCSS &amp; shadcn</h3>



<p>Für das Styling habe ich auf <strong>TailwindCSS</strong> gesetzt – ein Utility-First-CSS-Framework, das schnelles Prototyping und einheitliches Design ermöglicht.<br>Zusätzlich kam <strong>shadcn</strong> zum Einsatz, eine leichtgewichtige Component Library mit Fokus auf Barrierefreiheit, Dark Mode und Customizability.</p>



<p><strong>Vorteile dieser Kombination:</strong></p>



<ul class="wp-block-list">
<li>Konsistentes UI mit klarer Design-Sprache</li>



<li>Wiederverwendbare Komponenten</li>



<li>Effiziente Entwicklung durch Utility-Klassen</li>



<li>Code Ownership: Components werden einfach ins Projekt kopiert</li>
</ul>



<h3 class="wp-block-heading">Authentifizierung: Clerk</h3>



<p>Die Authentifizierung wird durch <strong>Clerk</strong> umgesetzt – denselben Anbieter, den ich bereits im ersten Semesterprojekt genutzt habe. Clerk bietet ein modernes User Management inklusive OAuth-Integration und JWT-Handling, was eine einfache Verbindung mit Convex und Next.js ermöglicht.</p>



<p>Durch Clerk konnte ich schnell eine sichere Login-, Logout- und Session-Logik aufsetzen, ohne selbst komplexe Authentifizierungssysteme implementieren zu müssen.</p>



<h3 class="wp-block-heading">Payment Provider: Stripe</h3>



<p>Ein zentrales Feature dieses Projekts war die <strong>Integration von Stripe</strong> als Payment Provider. Nutzer:innen können direkt über die Website eine Skiausfahrt buchen und bezahlen.<br>Dazu wurde das Stripe Checkout-System in die App eingebunden – inklusive <strong>Webhook-Handling</strong>, um Payment-Status-Änderungen serverseitig zu verarbeiten.</p>



<p><strong>Beispielhafte Flows:</strong></p>



<ul class="wp-block-list">
<li>User wählt eine Ausfahrt aus → Klick auf „Buchen“</li>



<li>Stripe Checkout öffnet sich → Zahlung erfolgt</li>



<li>Stripe sendet einen Webhook an das System → Buchung wird bestätigt und gespeichert</li>
</ul>



<p>Diese End-to-End-Integration war der Kern des Projekts und erforderte ein gutes Zusammenspiel zwischen <strong>Frontend, Convex Backend und Stripe Webhooks</strong>.</p>



<h2 class="wp-block-heading">Kommunikation &amp; Webhooks</h2>



<p>Ein spannender Teil des Projekts war die <strong>Kommunikation zwischen den verschiedenen Systemen</strong>.<br>Sowohl Stripe als auch Clerk arbeiten mit <strong>Webhooks</strong>, um Echtzeit-Informationen an das System zu senden (z. B. erfolgreiche Zahlungen oder neue Benutzer).<br>Die Webhooks werden über API-Routen in Next.js empfangen und anschließend in Convex weiterverarbeitet – beispielsweise um Buchungsdaten zu aktualisieren oder Rechnungen zu speichern.</p>



<h2 class="wp-block-heading">Herausforderungen &amp; Learnings</h2>



<p>Während der Entwicklung gab es mehrere interessante Herausforderungen:</p>



<ul class="wp-block-list">
<li><strong>Webhook-Handling:</strong> Das Zusammenspiel von Stripe, Clerk und Convex erfordert saubere Trennung von Sicherheits- und Logikschichten. Insbesondere das Validieren von Webhook-Signaturen war anfänglich fehleranfällig.</li>



<li><strong>Datenmodellierung in Convex:</strong> Da Convex ein eigenes Datenmodell nutzt, war es notwendig, sich in dessen Schema-System einzuarbeiten.</li>



<li><strong>SSR + Client-Komponenten:</strong> Der Wechsel zwischen Server- und Client-Komponenten im Next.js App Router war zunächst ungewohnt und erforderte ein gutes Verständnis des Rendering-Modells.</li>
</ul>



<p>Trotz dieser Hürden war die Entwicklung äußerst lehrreich – vor allem im Hinblick auf <strong>Payment-Flows, Security und API-Kommunikation</strong>.</p>



<h2 class="wp-block-heading">Fazit</h2>



<p>Das Club Dashboard war ein spannendes Projekt, das mir erstmals die Umsetzung einer <strong>vollständigen End-to-End-Integration mit Stripe</strong> ermöglicht hat.<br>Durch den Einsatz moderner Tools wie <strong>Next.js, Convex, Clerk und Stripe</strong> konnte ich einen funktionalen MVP umsetzen, der reale Buchungsprozesse abbildet.</p>



<p>Besonders interessant war zu sehen, wie gut sich die verschiedenen Services über <strong>Webhooks und API-Routen</strong> integrieren lassen – und wie wichtig saubere Datenflüsse und Sicherheit in einem Payment-System sind.</p>



<p>Im nächsten Schritt plane ich, das Dashboard um weitere Funktionalitäten zu erweitern, um einem produktionsreifen Produkt näher zu kommen, das sich veröffentlichen und vertreiben lässt.</p>



<h2 class="wp-block-heading">Screenshots</h2>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1996" height="1594" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/landing_page.jpg" alt="" class="wp-image-14844" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/landing_page.jpg 1996w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/landing_page-1536x1227.jpg 1536w" sizes="auto, (max-width: 1996px) 100vw, 1996px" /><figcaption class="wp-element-caption">Screenshot: Landing Page</figcaption></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1993" height="1591" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/ausfahrten.png" alt="" class="wp-image-14845" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/ausfahrten.png 1993w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/ausfahrten-1536x1226.png 1536w" sizes="auto, (max-width: 1993px) 100vw, 1993px" /><figcaption class="wp-element-caption">Screenshot: Ausfahrtenliste mit Buchungsoption</figcaption></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="2011" height="1600" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/dashboard.png" alt="" class="wp-image-14847" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/dashboard.png 2011w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/dashboard-1536x1222.png 1536w" sizes="auto, (max-width: 2011px) 100vw, 2011px" /><figcaption class="wp-element-caption">Screenshot: Ausfahrtenverwaltung am Dashboard</figcaption></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1990" height="1429" src="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/zahlungsinfos.png" alt="" class="wp-image-14848" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/zahlungsinfos.png 1990w, https://mobile.fhstp.ac.at/wp-content/uploads/2025/10/zahlungsinfos-1536x1103.png 1536w" sizes="auto, (max-width: 1990px) 100vw, 1990px" /><figcaption class="wp-element-caption">Screenshot: Eingebettete Stripe Account Komponenten am Dashboard</figcaption></figure>



<p></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/projekt-powda-club-dashboard/">Projekt | Powda Club-Dashboard</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Architecture of large frontend applications</title>
		<link>https://mobile.fhstp.ac.at/development/architecture-of-large-frontend-applications/</link>
		
		<dc:creator><![CDATA[Jan Weiß]]></dc:creator>
		<pubDate>Thu, 02 Oct 2025 06:06:11 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=14804</guid>

					<description><![CDATA[<p>Creating web applications with the size of a prototype is easy. Things get spicy when a frontend application has been under active development by multiple teams and for many years. Ideally, the right measures were taken at an early stage of a project, which allows it to grow in an ordered way. Anyway, it is <a class="read-more" href="https://mobile.fhstp.ac.at/development/architecture-of-large-frontend-applications/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/architecture-of-large-frontend-applications/">Architecture of large frontend applications</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Creating web applications with the size of a prototype is easy. Things get spicy when a frontend application has been under active development by multiple teams and for many years. Ideally, the right measures were taken at an early stage of a project, which allows it to grow in an ordered way. Anyway, it is never too late. With this article, I would like to present my learning on this topic, which resulted from working on such a large frontend application.</p>



<h2 class="wp-block-heading"><strong>Modularization</strong></h2>



<p>When you start a new Next or Nuxt application, you are tempted to throw all pages into the folder “pages” and all components into a folder “components,” etc. This will become a horrible mess once the application grows. My first and most important recommendation is to modularize the application ideally from the start. Each module holds its relevant code (pages, components, etc.).</p>



<p>It can be tricky to decide how to draw your modules. You can read the book “The Art of Micro Frontends” by Florian Rappl, which covers this topic in a chapter. The approach which has worked for me and my team was to first identify the domains of your application and make them modules. Later, you can split the code of the domains into further sub-modules representing individual features. With this clear structure, you will be able to navigate your code base easily and to see and enforce dependencies/relationships between the modules of your project.</p>



<p>You might want to convert some modules into micro-frontends, which are loaded at runtime. But be aware of the extra complexity which comes with micro-frontends. Again, I recommend reading the book “The Art of Micro Frontends” by Florian Rappl, which is a comprehensive guide in this regard.</p>



<h2 class="wp-block-heading"><strong>SOLID</strong></h2>



<p>When designing software, keeping the SOLID principles in mind is essential. Yet, it seems that there is only little awareness of this among web developers. For creating the architecture of your project, I want to especially highlight two principles.</p>



<p>Open/Closed Principle -> software entities should be open for extension but closed for modifications.<br>Dependency Inversion Principle -> depend upon abstractions, not concretes.</p>



<p>They will lead to a special approach when designing your code. Let me give you an example. In an e-commerce application, you might have a module holding the code for displaying a product and another module which holds an add-to-cart button. Now, according to the principles, you would create your product view to contain and expose a slot which receives the product data. The module containing the add-to-cart button registers the button inside the product view’s slot. The result is that the module with the product view is extended without having to have knowledge of the add-to-cart button.</p>



<h2 class="wp-block-heading"><strong>Feature flags</strong></h2>



<p>You modularized your application, and the code which belongs to the individual domains and features is in the respective location. You might have noticed that this structure encourages using feature flags to enable/disable modules. Feature flags might be necessary because your application is supposed to be distributed in different configurations. But feature flags have another interesting and powerful use: releasing features by activating a feature flag instead of by deploying your application. The idea is, when you are ready to release a feature, you deploy the application without the feature being activated. For more detailed information on the benefits and additional use cases of feature flags, please read the article &#8220;Feature Toggles (aka Feature Flags)“ by Pete Hodgson (<a href="https://martinfowler.com/articles/feature-toggles.html">https://martinfowler.com/articles/feature-toggles.html</a>).</p>



<h2 class="wp-block-heading"><strong>What’s next</strong></h2>



<p>I hope this article gave you good ideas on how to design your application. I am looking forward to comments and discussion as this is a very relevant topic to me. This article might require follow-ups which are dedicated to specific technical implementations of the described principles.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/architecture-of-large-frontend-applications/">Architecture of large frontend applications</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
