<?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>Studium Archives - Mobile USTP MKL</title>
	<atom:link href="https://mobile.fhstp.ac.at/category/studium/feed/" rel="self" type="application/rss+xml" />
	<link>https://mobile.fhstp.ac.at/category/studium/</link>
	<description>Die &#34;Mobile Forschungsgruppe&#34; der USTP, sie  sammelt hier alles zu den Themen Design, UX und Entwicklung mobiler Applikationen</description>
	<lastBuildDate>Wed, 14 Oct 2026 19:19:05 +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>Studium Archives - Mobile USTP MKL</title>
	<link>https://mobile.fhstp.ac.at/category/studium/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>print2mobile &#8211; no.bs. Tampons: Verpackung die aufklärt</title>
		<link>https://mobile.fhstp.ac.at/allgemein/print2mobile-no-bs-tampons-verpackung-die-aufklart/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/print2mobile-no-bs-tampons-verpackung-die-aufklart/#respond</comments>
		
		<dc:creator><![CDATA[Emma Murhammer]]></dc:creator>
		<pubDate>Wed, 14 Oct 2026 19:16:15 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=16077</guid>

					<description><![CDATA[<p>Tampons gehören zu den meistgenutzten Hygieneartikeln für Menschen mit Periode. Etwa jede zweite menstruierende Person greift zum Tampon. Dennoch wissen die wenigsten genau, was in ihrem Körper während dieser Zeit passiert oder warum sie jeden Monat ungefähr eine Woche leiden. Genau hier setzt no bs. an: mit einer Periodenprodukt-Verpackung, die nicht nur ein Produkt, sondern <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/print2mobile-no-bs-tampons-verpackung-die-aufklart/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/print2mobile-no-bs-tampons-verpackung-die-aufklart/">print2mobile &#8211; no.bs. Tampons: Verpackung die aufklärt</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Tampons gehören zu den meistgenutzten Hygieneartikeln für Menschen mit Periode. Etwa jede zweite menstruierende Person greift zum Tampon. Dennoch wissen die wenigsten genau, was in ihrem Körper während dieser Zeit passiert oder warum sie jeden Monat ungefähr eine Woche leiden.<sup data-fn="1677b77a-079b-45de-82b1-6c47ad02fff2" class="fn"><a href="#1677b77a-079b-45de-82b1-6c47ad02fff2" id="1677b77a-079b-45de-82b1-6c47ad02fff2-link">1</a></sup></p>



<p class="wp-block-paragraph">Genau hier setzt no bs. an: mit einer Periodenprodukt-Verpackung, die nicht nur ein Produkt, sondern auch Wissen vermittelt. Als Unternehmen<sup data-fn="852648c3-4f00-4a16-baf3-9dfbee2ca522" class="fn"><a href="#852648c3-4f00-4a16-baf3-9dfbee2ca522" id="852648c3-4f00-4a16-baf3-9dfbee2ca522-link">2</a></sup>, das nachhaltige und ethisch hergestellte Hygieneartikel anbietet, sieht no bs. sich in der Verantwortung aufzuklären. Das betrifft nicht nur die richtige Anwendung, sondern auch die Vorgänge im gesamten weiblichen Zyklus.</p>



<h2 class="wp-block-heading">Die Umsetzung</h2>



<p class="wp-block-paragraph">Auf der Packung von „no bs. tampons.“ sitzt ein QR-Code. Er führt zu einer Website, die den weiblichen Zyklus kurz und einfach erklärt. Der Gedanke dahinter ist eine Initiative unter dem Motto „mehr Aufklärung über den Zyklus“. Der Code lässt sich genauso auf Verpackung für Binden, Menstruationstassen oder Periodenunterwäsche drucken und wird damit zu einem gemeinsamen Zeichen für verschiedene Produkte.</p>



<p class="wp-block-paragraph">Auf der Website wird der Zyklus durch das Jahreszeiten-Modell aufbereitet. Geprägt haben es Alexandra Pope und Sjanie Hugo Wurlitzer, die Gründerinnen der „Red School“. Sie stellen die „inneren Jahreszeiten“ in ihrem Buch <em>Wild Power</em> vor, nach der Quelle 2017.<sup data-fn="60148ab5-ba75-48d5-b775-5625862a28c4" class="fn"><a href="#60148ab5-ba75-48d5-b775-5625862a28c4" id="60148ab5-ba75-48d5-b775-5625862a28c4-link">3</a></sup> Ähnliche Ideen gibt es vermutlich schon länger in der feministischen Literatur über Menstruation. Ich selber kenne es aus dem Buch &#8220;Superpower Periode&#8221; (Original: powerful) von Maisie Hill.<sup data-fn="6c44341e-bb4c-4a83-af0a-c68f5c67d04c" class="fn"><a href="#6c44341e-bb4c-4a83-af0a-c68f5c67d04c" id="6c44341e-bb4c-4a83-af0a-c68f5c67d04c-link">4</a></sup></p>



<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:65% auto"><figure class="wp-block-media-text__media"><img fetchpriority="high" decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/10/front_view_mockup-1540x800.png" alt="" class="wp-image-16079 size-full" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/10/front_view_mockup-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/10/front_view_mockup-770x400.png 770w" sizes="(max-width: 1540px) 100vw, 1540px" /></figure><div class="wp-block-media-text__content">
<p class="wp-block-paragraph">Gestalterisch habe ich mich für einen direkten, ironischen Ton entschieden. Die Seitenfläche mit der Frage „How bad are your cramps by the way?“ nimmt Leser:innen ernst, ohne belehrend zu wirken. </p>
</div></div>



<div style="height:13px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">Die zugehörige Website habe ich mit HTML, CSS und JavaScript umgesetzt. Die Grundstruktur und die Funktionalität entstanden durch gezieltes Prompting mit Claude Code. Das Design habe ich anschließend selbst angepasst und auch die Struktur mit den Card-Elementen eigenständig eingefügt. Die Seite ist bewusst sehr einfach gehalten, damit später genug Platz für funktionale Ergänzungen bleibt. Gehostet wird sie auf einer Subdomain meiner persönlichen Website, die auf einem Server von Hostinger läuft. Dadurch ist der QR-Code auf jedem Gerät abrufbar.</p>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-outline is-style-outline--1"><a class="wp-block-button__link has-pale-pink-color has-text-color has-link-color wp-element-button" href="https://no-bs.emmamurhammer.com/">Website besuchen</a></div>
</div>



<div style="height:42px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image size-large"><img decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/10/side_view_mockup-1540x800.png" alt="" class="wp-image-16083" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/10/side_view_mockup-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/10/side_view_mockup-770x400.png 770w" sizes="(max-width: 1540px) 100vw, 1540px" /></figure>



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



<p class="wp-block-paragraph">Die Website eignet sich gut für Kooperationen mit Organisationen, die sich gegen Periodenarmut engagieren oder weltweit Bildung für Mädchen fördern. Denkbar wären auch Partnerschaften mit Aidshilfen oder gynäkologischen Praxen. Dort könnten Flyer aufgelegt werden, die ebenfalls auf die Seite verweisen. Voraussetzung dafür ist, dass die Inhalte wissenschaftlich belegt sind.</p>



<p class="wp-block-paragraph">Darüber hinaus sind weitere Kooperationen möglich, zum Beispiel mit Zyklus- und Hormontrackern oder mit Fraueninitiativen. Auch Spendenaktionen für Menschen, die sich Hygieneprodukte nicht leisten können, wären eine sinnvolle Ergänzung. So kann aus einer einzelnen Verpackung eine Initiative werden, die viele Menschen erreicht.</p>



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


<ol class="wp-block-footnotes"><li id="1677b77a-079b-45de-82b1-6c47ad02fff2">VuMA. (2025). Wichtigste Hygieneprodukte für Frauen während der Menstruation in Deutschland in den Jahren 2014 bis 2018 &#8211; Deutschland. Statista. /statistik/daten/studie/181257/umfrage/verwendete-produkte-waehrend-der-menstruation/ <a href="#1677b77a-079b-45de-82b1-6c47ad02fff2-link" aria-label="Jump to footnote reference 1"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png" alt="↩" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</a></li><li id="852648c3-4f00-4a16-baf3-9dfbee2ca522">Das Unternehmen no bs. gibt es (noch <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> nicht wirklich und wurde nur für den Zweck dieses Projekts erstellt. <a href="#852648c3-4f00-4a16-baf3-9dfbee2ca522-link" aria-label="Jump to footnote reference 2"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png" alt="↩" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</a></li><li id="60148ab5-ba75-48d5-b775-5625862a28c4"><a href="https://www.redschool.net/">https://www.redschool.net/</a> <a href="#60148ab5-ba75-48d5-b775-5625862a28c4-link" aria-label="Jump to footnote reference 3"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png" alt="↩" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</a></li><li id="6c44341e-bb4c-4a83-af0a-c68f5c67d04c"><a href="https://maisiehill.com/books">https://maisiehill.com/books</a> <a href="#6c44341e-bb4c-4a83-af0a-c68f5c67d04c-link" aria-label="Jump to footnote reference 4"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png" alt="↩" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</a></li></ol>


<p class="wp-block-paragraph"></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/print2mobile-no-bs-tampons-verpackung-die-aufklart/">print2mobile &#8211; no.bs. Tampons: Verpackung die aufklärt</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mobile.fhstp.ac.at/allgemein/print2mobile-no-bs-tampons-verpackung-die-aufklart/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OnTime V2</title>
		<link>https://mobile.fhstp.ac.at/allgemein/ontime-v2/</link>
		
		<dc:creator><![CDATA[Sander Hahn]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 09:37:09 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Cross Plattform]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[supabase]]></category>
		<category><![CDATA[Typescript]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15971</guid>

					<description><![CDATA[<p>OnTime started because I didn&#8217;t want to pay for a time tracker. Version one only had that traccker and one Tauri 2 codebase that shipped to the web, Windows and Android. V2 lives in a new repository, but it is of course built on Version one. The tracker is still at its core and around <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/ontime-v2/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/ontime-v2/">OnTime V2</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">OnTime started because I didn&#8217;t want to pay for a time tracker. Version one only had that traccker and one Tauri 2 codebase that shipped to the web, Windows and Android.</p>



<p class="wp-block-paragraph">V2 lives in a new repository, but it is of course built on Version one. The tracker is still at its core and around it, OnTime now handles teams, invoices and payments.</p>



<h2 class="wp-block-heading">What changed</h2>



<p class="wp-block-paragraph">In V1, one person tracked their own time but in V2, everything happens inside <strong>workspaces</strong>. A workspace can consist of just you or a whole team and every member has one of four roles: owner, admin, manager or member.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Dark-1540x800.png" alt="" class="wp-image-15973" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Dark-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Dark-770x400.png 770w" sizes="(max-width: 1540px) 100vw, 1540px" /></figure>



<p class="wp-block-paragraph">But the basics are of course still there: a timer, manual entries and clients, projects and tasks with their own detail pages. The calendar is now shared and even updates live across devices. Projects can have budgets that send a notification when they cross a threshold. The whole app is in English and German and on mobile it works offline thanks to a persisted query cache.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Overview-Dark-1540x800.png" alt="" class="wp-image-15974" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Overview-Dark-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Overview-Dark-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<h2 class="wp-block-heading">Invoices and payments<br></h2>



<p class="wp-block-paragraph">This is where V2 changes the most from its previous version. Billable time becomes an invoice and when you send it, an Edge Function renders it as a PDF and <strong>freezes</strong> it. If you edit the underlying time entries later, the document the client already received doesn&#8217;t change.</p>



<p class="wp-block-paragraph">Additionally, OnTime connects to your bank through <strong>Enable Banking</strong>. The connection is read-only by design and you bring your own credentials, which are stored encrypted in Supabase Vault. A scheduled pg_cron job pulls in transactions and matches them against open invoices. When a match is confident, the invoice is marked paid automatically. Everything else waits in a queue for one-click review.<br></p>



<h2 class="wp-block-heading">Database changes</h2>



<p class="wp-block-paragraph">V1&#8217;s database only had to serve one person tracking their own hours. V2 needed a real data model, so I didn&#8217;t patch the old schema and started from the start.</p>



<p class="wp-block-paragraph">As said before, <strong>Everything belongs to a workspace</strong>: Clients, projects, tasks, time entries and invoices all hang off a workspace and every row knows which workspace it belongs to. That one change is what makes teams possible. It&#8217;s also what the security model is built on.</p>



<p class="wp-block-paragraph">Also, every table has row-level security policies that check the caller&#8217;s workspace and role before returning a single row. Views run with <code>security_invoker</code>, so they apply the permissions of the person querying them instead of quietly bypassing them. Owners, admins, managers and members all hit the same tables and get different answers. Since the frontend isn&#8217;t trusted to enforce any of this, pgTAP suites test the rules against a real database.</p>



<p class="wp-block-paragraph">Another security measure was to add a timestamp to entries when they get deleted. Now they are moved to a trash view, where they can be restored. A pg_cron job purges them for good once they&#8217;ve been in the trash long enough, so nobody has to clean up by hand.</p>



<p class="wp-block-paragraph">An invoice can&#8217;t point at time entries and hourly rates, because those can change or be edited. When an invoice is sent, it stores a JSONB snapshot of everything it was built from and the PDF is frozen alongside it. Rates also keep a history, so billing a project in March uses March&#8217;s rate even if it went up in June. Invoice numbers are generated per workspace and restart each year.</p>



<p class="wp-block-paragraph">pg_cron also triggers the bank sync so that transactions come in on a schedule, get matched against open invoices and confident matches mark the invoice as paid. The bank credentials never sit in a plain column and are encrypted in Supabase Vault.</p>



<p class="wp-block-paragraph">The shared calendar and the notifications subscribe to database changes through Supabase Realtime. When someone stops a timer on their phone, the entry shows up on everyone else&#8217;s desktop without a refresh.</p>



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



<p class="wp-block-paragraph">Tests run in three layers:</p>



<ul class="wp-block-list">
<li><strong>Vitest</strong> for units and components</li>



<li><strong>Playwright</strong> end-to-end tests against a preview build</li>



<li><strong>pgTAP</strong> for the security rules</li>
</ul>



<p class="wp-block-paragraph">Unit and end-to-end coverage are combined into one number and uploaded to Codecov on every CI run. Right now I have about 40% coverage but that will still be improved in later versions.</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-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15980" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Dark-1-1540x800.png" alt="" class="wp-image-15980" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Dark-1-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Dark-1-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15978" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Light-1540x800.png" alt="" class="wp-image-15978" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Light-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Calendar-Light-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15983" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoice-Detail-Dark-1540x800.png" alt="" class="wp-image-15983" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoice-Detail-Dark-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoice-Detail-Dark-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15985" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoice-Detail-Light-1540x800.png" alt="" class="wp-image-15985" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoice-Detail-Light-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoice-Detail-Light-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15984" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoices-Dark-1540x800.png" alt="" class="wp-image-15984" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoices-Dark-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoices-Dark-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15982" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoices-Light-1540x800.png" alt="" class="wp-image-15982" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoices-Light-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Invoices-Light-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15981" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Overview-Light-1540x800.png" alt="" class="wp-image-15981" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Overview-Light-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Overview-Light-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="680" data-id="15977" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Payment-Review-Dark-1-1540x680.png" alt="" class="wp-image-15977"/></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="680" data-id="15979" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Payment-Review-Light-1540x680.png" alt="" class="wp-image-15979"/></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15987" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Projects-Dark-1540x800.png" alt="" class="wp-image-15987" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Projects-Dark-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Projects-Dark-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15988" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Projects-Light-1540x800.png" alt="" class="wp-image-15988" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Projects-Light-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/OnTimeV2-Projects-Light-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>
</figure>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/ontime-v2/">OnTime V2</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Designing Offline-First iOS Apps: Local State, Persistence, and Sync Without Losing User Trust</title>
		<link>https://mobile.fhstp.ac.at/allgemein/designing-offline-first-ios-apps-local-state-persistence-and-sync-without-losing-user-trust/</link>
		
		<dc:creator><![CDATA[Melanie Maier]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 08:37:26 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[offline-first]]></category>
		<category><![CDATA[persistence]]></category>
		<category><![CDATA[Sync]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15926</guid>

					<description><![CDATA[<p>Abstract Many mobile apps look simple until they must preserve an unfinished edit, work offline, survive a crash, and reconcile changes from two devices. Then “save and sync” becomes an architecture, and a promise to the user. An offline-first iOS app treats its local store as the immediate source of truth. User actions update it <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/designing-offline-first-ios-apps-local-state-persistence-and-sync-without-losing-user-trust/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/designing-offline-first-ios-apps-local-state-persistence-and-sync-without-losing-user-trust/">Designing Offline-First iOS Apps: Local State, Persistence, and Sync Without Losing User Trust</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Abstract</h2>



<p class="wp-block-paragraph">Many mobile apps look simple until they must preserve an unfinished edit, work offline, survive a crash, and reconcile changes from two devices. Then “save and sync” becomes an architecture, and a promise to the user.</p>



<p class="wp-block-paragraph">An offline-first iOS app treats its local store as the immediate source of truth. User actions update it first; synchronization is separate and retryable. State boundaries must be explicit, writes safe, conflicts explainable, and the interface honest about data stored only locally.</p>



<p class="wp-block-paragraph">This article follows that model from SwiftUI state through persistence, autosave, change tracking, conflicts, and failure UX.</p>



<h2 class="wp-block-heading">1. Why Offline-First Still Matters</h2>



<p class="wp-block-paragraph">In 2026, fast networks are common, reliable connectivity is not. A phone can enter a tunnel, encounter a captive portal, or lose authentication. A request may reach the server even when its response never reaches the client.</p>



<p class="wp-block-paragraph">Offline-first begins with a rule: the user performs the app’s core work against local data. The app records the intent durably and synchronizes later. A task app should not discard a completed task because the server timed out.</p>



<p class="wp-block-paragraph">This is different from caching. A cache is usually disposable and can be reconstructed from an authoritative source. Offline-created user data cannot. If deleting the local copy would destroy information that exists nowhere else, it is not “just a cache.”</p>



<p class="wp-block-paragraph">Reachability is not permission to write. Network status can help decide when to attempt synchronization, but it cannot prove that the next request will succeed. Foundation can wait through <code>URLSessionConfiguration.waitsForConnectivity</code>, but the durable queue, not a green icon, is what makes a write reliable (<a href="https://developer.apple.com/documentation/foundation/urlsessionconfiguration/waitsforconnectivity">Apple: </a><code><a href="https://developer.apple.com/documentation/foundation/urlsessionconfiguration/waitsforconnectivity">waitsForConnectivity</a></code>).</p>



<p class="wp-block-paragraph">The useful mental model is:</p>



<ol start="1" class="wp-block-list">
<li>accept the user’s action</li>



<li>validate it locally</li>



<li>commit it locally</li>



<li>render the committed result</li>



<li>enqueue synchronization</li>



<li>retry safely until the server acknowledges it</li>
</ol>



<p class="wp-block-paragraph">The network path affects step five, not the validity of steps one through four.</p>



<h2 class="wp-block-heading">2. Local State Is Not Temporary State</h2>



<p class="wp-block-paragraph">SwiftUI makes state easy to declare, which can make unlike kinds of state look deceptively similar. A robust app distinguishes at least three layers.</p>



<p class="wp-block-paragraph"><strong>View state</strong>&nbsp;exists only to present or control the current interface: whether a sheet is open, which tab is selected, a search field’s draft text, or the expansion state of a disclosure group.&nbsp;<code>@State</code>&nbsp;is often appropriate because SwiftUI owns that value for the lifetime of the view identity.</p>



<p class="wp-block-paragraph"><strong>Domain state</strong>&nbsp;represents meaningful work: a document title, completed task, or pending deletion. It must not depend on whether a view exists. Observation and&nbsp;<code>@Observable</code>&nbsp;help present domain objects, but observability is not persistence.</p>



<p class="wp-block-paragraph"><strong>Persistent application state</strong>&nbsp;has crossed a durability boundary. It has been written to a file or store that can be reconstructed after relaunch. SwiftData’s&nbsp;<code>ModelContainer</code>&nbsp;and&nbsp;<code>ModelContext</code>, a Core Data persistent container, or a purpose-built SQLite layer live here.</p>



<p class="wp-block-paragraph">The distinction matters during editing. Binding a field directly to a persistent model saves half-finished values. That may suit notes, but not a bank transfer or an object whose fields must remain consistent. In those cases, edit a draft, validate it, and commit the complete change in one transaction.</p>



<p class="wp-block-paragraph">A practical dependency direction is:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
SwiftUI view → use case / repository → local store
                                <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2198.png" alt="↘" class="wp-smiley" style="height: 1em; max-height: 1em;" /> sync outbox
</pre></div>


<p class="wp-block-paragraph">Views request operations such as&nbsp;<code>completeTask</code>; they do not decide how JSON is replaced or CloudKit records are merged. This makes offline behavior testable without UI or a real server.</p>



<h2 class="wp-block-heading">3. Choosing a Persistence Strategy</h2>



<p class="wp-block-paragraph">Choose the smallest persistence mechanism that preserves the data’s structure, query needs, migrations, and ownership.</p>



<p class="wp-block-paragraph"><strong>UserDefaults</strong>&nbsp;is for small preferences such as sort order or a dismissed onboarding flag. It is not a document database or an outbox.</p>



<p class="wp-block-paragraph"><strong>JSON or property-list files</strong>&nbsp;suit small, document-shaped datasets loaded and replaced as a unit. They are transparent and exportable. Once the app needs indexed queries, relationships, concurrent writers, or a large sync log, one JSON file becomes an improvised database.</p>



<p class="wp-block-paragraph"><strong>SwiftData</strong>&nbsp;is a natural high-level choice for many new Apple-platform apps. It integrates persistent models with Swift and SwiftUI queries. Its main context supports autosave in app configurations, manually created contexts do not inherit that behavior. Design schema migrations before a model rename ships (<a href="https://developer.apple.com/videos/play/wwdc2023/10196/">Apple: Dive deeper into SwiftData</a>,&nbsp;<a href="https://developer.apple.com/videos/play/wwdc2025/291/">Apple: schema migration</a>).</p>



<p class="wp-block-paragraph"><strong>Core Data</strong>&nbsp;remains strong for mature apps, complex graphs, and established migration plans.&nbsp;<code>NSPersistentContainer</code>encapsulates the stack, while persistent history can expose transactions made elsewhere. SwiftData is not merely “Core Data with nicer syntax”. Evaluate requirements instead of choosing by age.</p>



<p class="wp-block-paragraph"><strong>SQLite</strong>&nbsp;fits explicit schemas, specialized indexes, predictable SQL, or tight transaction control. An atomic commit makes all transaction changes visible or none. Write-ahead logging can let readers continue during writes, though checkpointing and durability settings still matter (<a href="https://sqlite.org/atomiccommit.html">SQLite: Atomic Commit</a>,&nbsp;<a href="https://sqlite.org/wal.html">SQLite: WAL</a>).</p>



<h2 class="wp-block-heading">4. Autosave and Data Integrity</h2>



<p class="wp-block-paragraph">Autosave is a user-experience policy, not an integrity mechanism. It answers&nbsp;<em>when the app attempts to persist</em>, not&nbsp;<em>whether a multi-part change is valid, atomic, or recoverable</em>.</p>



<p class="wp-block-paragraph">For free-form text, saving after every keystroke wastes work. A short debounce coalesces edits, but creates a window where input exists only in memory. Flush critical drafts when editing ends and when the scene changes phase.</p>



<p class="wp-block-paragraph">For files, write to an auxiliary file and replace the original only after success. Foundation’s atomic option follows this approach (<a href="https://developer.apple.com/documentation/foundation/nsdata/writingoptions/atomic">Apple:&nbsp;</a><code><a href="https://developer.apple.com/documentation/foundation/nsdata/writingoptions/atomic">NSData.WritingOptions.atomic</a></code>). Keep a last known-good version when corruption is costly, a backup matters only if restore is tested.</p>



<p class="wp-block-paragraph">For database persistence, group invariant-related changes in one transaction. Creating an order and decrementing inventory in separate saves exposes an impossible intermediate state after a crash. Transaction boundaries should follow domain meaning, not screen layout.</p>



<p class="wp-block-paragraph">Every model needs a migration story. Use stable identifiers independent of local row IDs, version schemas, and test upgrades from every supported release. Never answer migration failure by silently deleting the user’s store.</p>



<p class="wp-block-paragraph">Treat storage errors as first-class outcomes. Disk space can run out, encoding can fail, and validation can reject a save.&nbsp;<code>try? context.save()</code>&nbsp;may create a quiet interface while hiding that data was never durable.</p>



<h2 class="wp-block-heading">5. Sync Is a Trust Problem</h2>



<p class="wp-block-paragraph">Synchronization is often drawn as two arrows between phone and cloud. Inside are duplicate requests, reordering, partial failure, concurrent edits, deletion, and expired authentication.</p>



<p class="wp-block-paragraph">A trustworthy design separates&nbsp;<strong>local durability</strong>&nbsp;from&nbsp;<strong>remote synchronization</strong>. Each mutation creates the domain change and an outbox entry in one transaction. A worker sends operations, records acknowledgements, applies remote changes, and retries with backoff. After a crash, the outbox still exists.</p>



<p class="wp-block-paragraph">Each operation should be idempotent. Give it a stable operation ID so a server can recognize a retry. If the server receives the request but the client loses the response, retrying must not create a duplicate object or repeat a payment.</p>



<p class="wp-block-paragraph">Timestamps are weak ordering mechanisms because device clocks differ. Prefer server revisions, advancing change tokens, or per-record versions. SwiftData History exposes chronological transactions and explicitly supports remote sync and out-of-process changes (<a href="https://developer.apple.com/videos/play/wwdc2024/10075/">Apple: SwiftData history</a>,&nbsp;<a href="https://developer.apple.com/documentation/swiftdata/fetching-and-filtering-time-based-model-changes">Apple: time-based changes</a>).</p>



<p class="wp-block-paragraph">HTTP offers concurrency semantics: the server returns an&nbsp;<code>ETag</code>, and the client sends&nbsp;<code>If-Match</code>&nbsp;when updating. If the resource changed, the precondition fails instead of overwriting newer data (<a href="https://www.rfc-editor.org/rfc/rfc9110">RFC 9110</a>). CloudKit similarly gives&nbsp;<code>CKRecord</code>&nbsp;a change tag for synchronization (<a href="https://developer.apple.com/documentation/cloudkit/ckrecord">Apple:&nbsp;</a><code><a href="https://developer.apple.com/documentation/cloudkit/ckrecord">CKRecord</a></code>).</p>



<p class="wp-block-paragraph">The app should model sync state explicitly, for example:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
enum SyncState: Equatable {
    case localOnly
    case queued
    case syncing
    case synced(revision: String)
    case conflict
    case blocked(reason: BlockReason)
}
</pre></div>


<p class="wp-block-paragraph">Do not infer sync from the absence of an error. A request that has not started is not synchronized, and expired authentication differs from a timeout.</p>



<h2 class="wp-block-heading">6. Conflict Handling and External Sources</h2>



<p class="wp-block-paragraph">Conflict policy must be defined per entity and sometimes per field. “Last write wins” is simple, but it can silently erase work and becomes especially unsafe when “last” depends on device clocks.</p>



<p class="wp-block-paragraph">Some data merges automatically: independent fields can merge separately and tag sets may use union semantics. Collaborative text needs a purpose-built algorithm such as a CRDT. It should not be improvised from&nbsp;<code>updatedAt</code>.</p>



<p class="wp-block-paragraph">Other conflicts need a human. Preserve both versions, show meaningful differences, and offer “Your edit from 10:42” versus “Edit from iPad at 10:45,” not merely “local” and “remote.”</p>



<p class="wp-block-paragraph">Deletions deserve their own model. If a deleted record vanishes immediately, another offline device may later re-upload it. A tombstone—an identifier, deletion revision, and retention period—allows deletion to propagate. Purge it only after the system’s synchronization window and device assumptions make resurrection acceptably unlikely.</p>



<p class="wp-block-paragraph">External sources also need ownership rules:</p>



<ul class="wp-block-list">
<li><strong>Read-only reference data:</strong> cache locally, display its age, and replace it from the source. Never upload it as if the user authored it</li>



<li><strong>Imported data:</strong> record provenance and the external identifier. Decide whether import creates an owned snapshot or maintains a live link</li>



<li><strong>Locally editable mirrors:</strong> keep the source version alongside pending local changes. Rebase or surface a conflict when the source changes</li>



<li><strong>External deletion:</strong> distinguish “no longer available upstream” from “user deleted locally.” Preserve local notes or derived records when policy allows</li>
</ul>



<p class="wp-block-paragraph">CloudKit subscriptions can signal record creation, modification, and deletion, but they only trigger fetching. They do not replace a durable local store or change token (<a href="https://developer.apple.com/documentation/cloudkit/ckrecordzonesubscription">Apple:&nbsp;</a><code><a href="https://developer.apple.com/documentation/cloudkit/ckrecordzonesubscription">CKRecordZoneSubscription</a></code>).</p>



<h2 class="wp-block-heading">7. UX for Failure</h2>



<p class="wp-block-paragraph">Offline-first UX should communicate consequences, not infrastructure. Users need three answers: Is my work saved here? Is it available elsewhere? Do I need to act?</p>



<p class="wp-block-paragraph">Use calm, specific status language:</p>



<ul class="wp-block-list">
<li><strong>Saved on this iPhone</strong> — the local transaction committed</li>



<li><strong>Waiting to sync</strong> — no action is normally required</li>



<li><strong>Syncing…</strong> — work is in progress</li>



<li><strong>Couldn’t sync. We’ll retry.</strong> — the failure is transient</li>



<li><strong>Sign in to continue syncing</strong> — user action is required</li>



<li><strong>Two versions need your review</strong> — silent merging would risk data loss</li>
</ul>



<p class="wp-block-paragraph">Avoid blocking alerts for routine failures. Prefer inline status, a persistent account banner, or sync-details screen. Reserve modal interruption for unsafe actions or imminent data loss.</p>



<p class="wp-block-paragraph">Optimistic UI is appropriate only after the local commit succeeds. If a user marks a task complete, the interface can update immediately because the durable local state already represents that action. If the save fails, keep the draft visible, explain that it is not yet stored, and offer a retry or export path.</p>



<p class="wp-block-paragraph">Expose “last synchronized” and pending changes when consequential. Never show a cloud checkmark merely because the device has connectivity. Do not encode sync state only in color. Provide text for VoiceOver.</p>



<p class="wp-block-paragraph">Test sequences, not isolated errors: edit offline, terminate, relaunch, edit elsewhere, reconnect, receive a conflict, lose connectivity during resolution, and retry. Also test duplicate responses, full storage, corruption, external deletion, and schema upgrades with a non-empty outbox.</p>



<h2 class="wp-block-heading">8. Conclusion</h2>



<p class="wp-block-paragraph">Good offline-first architecture is mostly invisible. The app opens with useful data, accepts work immediately, survives interruption, and later converges without surprises. Achieving that experience requires more than adding a cache or calling&nbsp;<code>save()</code>&nbsp;from SwiftUI.</p>



<p class="wp-block-paragraph">Separate view state from durable domain state. Choose persistence by data shape and guarantees. Make writes atomic at meaningful boundaries. Track mutations with stable identities and versions. Treat sync as a retryable state machine, not a request callback. Define ownership, deletion, and conflict policies before the edge cases arrive. Above all, tell the truth in the interface about what is saved locally and what has reached another device.</p>



<p class="wp-block-paragraph">Users rarely praise an app for its outbox, migration plan, or tombstones. They simply decide that the app feels dependable. That judgment is the real product of an offline-first design.</p>



<h2 class="wp-block-heading">Sources and Further Reading</h2>



<ul class="wp-block-list">
<li>Apple, <a href="https://developer.apple.com/videos/play/wwdc2023/10196/">Dive deeper into SwiftData (WWDC23)</a>.</li>



<li>Apple, <a href="https://developer.apple.com/videos/play/wwdc2024/10075/">Track model changes with SwiftData history (WWDC24)</a>.</li>



<li>Apple, <a href="https://developer.apple.com/videos/play/wwdc2025/291/">SwiftData: Dive into inheritance and schema migration (WWDC25)</a>.</li>



<li>Apple, <a href="https://developer.apple.com/documentation/swiftdata/fetching-and-filtering-time-based-model-changes">Fetching and filtering time-based model changes</a>.</li>



<li>Apple, <code><a href="https://developer.apple.com/documentation/coredata/nspersistentcontainer">NSPersistentContainer</a></code>.</li>



<li>Apple, <code><a href="https://developer.apple.com/documentation/foundation/nsdata/writingoptions/atomic">NSData.WritingOptions.atomic</a></code>.</li>



<li>Apple, <code><a href="https://developer.apple.com/documentation/foundation/urlsessionconfiguration/waitsforconnectivity">URLSessionConfiguration.waitsForConnectivity</a></code>.</li>



<li>Apple, <code><a href="https://developer.apple.com/documentation/cloudkit/ckrecord">CKRecord</a></code> and <code><a href="https://developer.apple.com/documentation/cloudkit/ckrecordzonesubscription">CKRecordZoneSubscription</a></code>.</li>



<li>SQLite, <a href="https://sqlite.org/atomiccommit.html">Atomic Commit in SQLite</a> and <a href="https://sqlite.org/wal.html">Write-Ahead Logging</a>.</li>



<li>IETF, <a href="https://www.rfc-editor.org/rfc/rfc9110">RFC 9110: HTTP Semantics</a>.</li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/designing-offline-first-ios-apps-local-state-persistence-and-sync-without-losing-user-trust/">Designing Offline-First iOS Apps: Local State, Persistence, and Sync Without Losing User Trust</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Designing a Calm Planning Experience: From Wireframes to a Coherent Visual Identity</title>
		<link>https://mobile.fhstp.ac.at/ux/design/designing-a-calm-planning-experience-from-wireframes-to-a-coherent-visual-identity/</link>
		
		<dc:creator><![CDATA[Melanie Maier]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 08:01:13 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[UI-Design]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15911</guid>

					<description><![CDATA[<p>Software projects are often described through architecture, data models, and technical milestones. Interface design tends to appear later in that story, as if it were simply the visible layer added once the important work is complete. During the development of this personal planning app, I experienced almost the opposite. The design process helped define how <a class="read-more" href="https://mobile.fhstp.ac.at/ux/design/designing-a-calm-planning-experience-from-wireframes-to-a-coherent-visual-identity/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/ux/design/designing-a-calm-planning-experience-from-wireframes-to-a-coherent-visual-identity/">Designing a Calm Planning Experience: From Wireframes to a Coherent Visual Identity</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Software projects are often described through architecture, data models, and technical milestones. Interface design tends to appear later in that story, as if it were simply the visible layer added once the important work is complete. During the development of this personal planning app, I experienced almost the opposite. The design process helped define how the product should behave, what kind of relationship it should have with its users, and which parts needed to remain simple as the underlying system became more complex.</p>



<p class="wp-block-paragraph">The project is still in development, and its name, complete concept, and current interface are intentionally not public yet. This article therefore does not present a product reveal. Instead, it focuses on the design process between March and August 2026: how the interface developed from functional wireframes into a more coherent visual system, how collaboration influenced the result, and how repeated feedback changed my understanding of clarity, accessibility, and visual identity.</p>



<p class="wp-block-paragraph">The app was developed during the second semester of the Master Interactive Media program. Its technical foundation is an iOS application written in Swift, but this project was mainly concerned with screen design and brand development. The public scope covers the basic screens already named in the development article: home, calendar and list overviews, related detail pages, and forms for calendar entries, list items, and reminders.</p>



<h2 class="wp-block-heading">Beginning with structure</h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Wireframes-1-1540x800.png" alt="" class="wp-image-15921" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Wireframes-1-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Wireframes-1-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<p class="wp-block-paragraph">The first design phase consisted of wireframes for these core functions. At that point, the goal was not to decide on colors, fonts, or icon styles. The wireframes were used to understand information hierarchy and navigation: What should appear first on the home screen? How much information belongs in an overview? When does an item need its own detail page? Which actions should be immediately available, and which can remain one level deeper?</p>



<p class="wp-block-paragraph">This phase was deliberately simple. Boxes represented content areas, placeholder text represented labels, and navigation elements were reduced to their basic purpose. It also exposed how quickly a planning interface can become crowded. Even the basic screens combine dates, titles, statuses, categories, actions, navigation, and secondary information. The home screen needed to offer orientation, overviews had to support scanning, and forms required a more guided rhythm.</p>



<p class="wp-block-paragraph">One important lesson from this stage was that visual hierarchy begins before visual styling. If the structure does not make priorities clear, stronger colors and larger headings only make the confusion more visible. The early wireframes therefore became a reference throughout the later process. Whenever a refined screen started to feel overloaded, I could return to the basic structure and ask whether the added visual elements were supporting the original purpose or competing with it.</p>



<h2 class="wp-block-heading">From wireframes to the first design screens</h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/firstDesign-1540x800.png" alt="" class="wp-image-15922" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/firstDesign-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/firstDesign-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<p class="wp-block-paragraph">The next phase translated the wireframes into the first designed screens. This was the point where the project began to develop a personality. Typography, rounded forms, color relationships, icons, cards, borders, and spacing were introduced. The interface was meant to feel personal and approachable, so the first visual direction leaned strongly toward a playful style.</p>



<p class="wp-block-paragraph">At first, this seemed appropriate. Planning is a daily and personal activity, and a playful interface offered a contrast to the strict appearance of many productivity tools. However, this phase also demonstrated that friendliness and playfulness are not the same thing. As more screens were added, decorative forms, multiple outlines, different icon styles, and expressive typography created too many points of attention. What worked as an isolated detail did not always work as part of a growing system.</p>



<p class="wp-block-paragraph">The first design screens were therefore valuable precisely because they were not final. They made the intended personality visible, but they also revealed where that personality needed more discipline. The project had reached the stage where individual screens could no longer be evaluated only as attractive compositions. They had to work as one product.</p>



<h2 class="wp-block-heading">Collaboration as a design process</h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/WhatsApp-Image-2026-08-04-at-16.12.50-1540x800.jpeg" alt="" class="wp-image-15923" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/WhatsApp-Image-2026-08-04-at-16.12.50-1540x800.jpeg 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/WhatsApp-Image-2026-08-04-at-16.12.50-770x400.jpeg 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<p class="wp-block-paragraph">During the visual development, I worked with a graphic design student who was responsible for developing the logo and the custom icons and who also proposed directions for the color concept. She is not named here, but her role in the process was substantial. I acted as the stakeholder for the application: I explained the intended character and requirements, reviewed ideas and intermediate states, and made decisions about how the graphic work should connect to the interface.</p>



<p class="wp-block-paragraph">The collaboration was not organized as a single briefing followed by a finished delivery. She shared sketches, variants, and intermediate states, and we discussed which qualities felt appropriate while the interface itself was evolving. I often approached an element through function: Is the icon understandable? Can the asset be used consistently in Swift? Her perspective added questions of visual rhythm, shape language, balance, and recognition.</p>



<p class="wp-block-paragraph">The logo and icons became important anchors for the emerging identity. Their development introduced more organic forms into a product that still needed a clear structure. This tension became one of the most useful ideas in the project: the interface could be calm and organized without becoming cold, and it could retain distinctive, playful details without allowing every component to become expressive.</p>



<p class="wp-block-paragraph">The color proposals connected the graphic identity to the screen design, but applying a palette to an interface is different from presenting it in a visual study. Colors that look balanced together may not provide enough contrast for text, and a shade that works in an illustration may be too prominent across a large card. The collaboration provided the visual material, while the interface work tested it under practical conditions.</p>



<h2 class="wp-block-heading">Feedback from recurring test users</h2>



<p class="wp-block-paragraph">Alongside the design collaboration, I repeatedly showed the screens to approximately five test users. The group was not statistically representative; its value came from continuity. The same people saw several stages and could react to changes over time.</p>



<p class="wp-block-paragraph">Two issues appeared repeatedly: text was sometimes too small, and the contrast between text and background colors was sometimes too weak. The feedback revealed the difference between designing at full size on a computer and using the result on a phone. A composition can look spacious in a design tool while becoming tiring at actual device size. Because users need to identify dates, items, categories, and actions quickly, readability is part of the core interaction rather than an accessibility layer added later.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="362" height="156" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Calendar-Card.png" alt="" class="wp-image-15924"/></figure>



<p class="wp-block-paragraph">In response, font sizes were reconsidered, text colors were strengthened, and some relationships between foreground and background were simplified. The process also made me more cautious about using color to create hierarchy. If several shades are close in brightness, they may create a harmonious palette but fail to establish a useful reading order. Contrast has to work both aesthetically and functionally.</p>



<p class="wp-block-paragraph">The users also identified screens that felt too busy even when every individual element was understandable. Familiarity reduces perceived complexity: after working on a screen for a long time, I already know where to look, while a test user does not. The central question gradually changed from whether the design looked friendly to whether it helped users feel oriented.</p>



<h2 class="wp-block-heading">Moving from playful to calm</h2>



<p class="wp-block-paragraph">The strongest change between the first designs and the refined screens was the overall design language. The earlier versions were visibly more playful. Over time, the interface became quieter, clearer, and more structured. This did not mean removing all personality. Instead, playful qualities were concentrated in selected places, particularly in organic forms and custom icon details, while the main layout became more restrained.</p>



<p class="wp-block-paragraph">Color was the most challenging part of this transition. The palette had to communicate warmth and individuality without reducing legibility or making the interface visually heavy. Several versions were needed before the relationship between light surfaces, darker functional elements, and accent colors felt balanced. The final direction is less about using many colors and more about giving each color a clear role.</p>



<p class="wp-block-paragraph">The refinement also affected borders, cards, spacing, and typography. Reducing unnecessary boundaries allowed alignment to do more of the organizational work. Headings, secondary information, form labels, and actionable text received clearer roles. The typeface could support personality, but size, weight, spacing, and contrast had to support usability.</p>



<p class="wp-block-paragraph">The same principle applied to iconography. Custom icons helped preserve the organic and personal character of the project, but an icon family also needs internal rules. Stroke weight, level of detail, filled and outlined states, and the relationship between icon and label all affect consistency. The icon work therefore became more than a collection of illustrations. It became the beginning of a visual grammar.</p>



<h2 class="wp-block-heading">Designing a system rather than isolated screens</h2>



<p class="wp-block-paragraph">By the refinement stage, the screen set included the home screen, calendar and list overviews, calendar and list detail pages, and the add forms for calendar entries, list items, and reminders. Although this remains only the basic functional scope, it is already broad enough to expose inconsistencies. A heading that works on the home screen may occupy too much space in a form. A card that works for an upcoming event may not work for a list item. A navigation control that feels obvious on an overview may be ambiguous on a detail page.</p>



<p class="wp-block-paragraph">This encouraged a more systematic approach. Instead of adjusting every screen independently, I began to think in reusable decisions: spacing intervals, text roles, card behavior, icon states, color functions, and recurring navigation patterns. This is also where the design process connected directly to the Swift implementation. Reusable SwiftUI components are easier to create when the visual rules are clear. Conversely, implementing a component across several screens quickly reveals where a design rule is too specific to one mock-up.</p>



<p class="wp-block-paragraph">The relationship between design and development was iterative. Screens informed the component structure, and implementation challenged the screens. Small differences are easy to draw but harder to justify when they require separate code paths. Variation therefore had to become intentional.</p>



<p class="wp-block-paragraph">The brand book developed alongside this consolidation. It brought together the values, personality, tone of voice, typography, colors, icon principles, and product experience guidelines that had emerged through the previous months. Creating it forced decisions that individual screens could postpone and turned visual preferences into shared rules.</p>



<p class="wp-block-paragraph">The brand identity can be summarized through a few qualities: clear, empathetic, and reliable. These qualities function as design criteria rather than promotional adjectives. Clarity requires an understandable hierarchy. Empathy means avoiding language and interactions that create unnecessary pressure. Reliability includes predictable navigation, legible states, and careful treatment of user data. A distinctive visual style is useful only when it supports these qualities.</p>



<h2 class="wp-block-heading">A cautious look toward adaptive interfaces</h2>



<p class="wp-block-paragraph">One future direction being explored is an adaptive interface. It has not yet been implemented, and the details remain intentionally broad. The basic idea is that the presentation could respond to screen size, accessibility preferences, or explicitly chosen modes instead of showing the same density at all times.</p>



<p class="wp-block-paragraph">However, adaptation creates a design risk. An interface that changes too freely can become difficult to learn and may reduce trust. Important navigation should remain predictable, and users should understand why a view has changed. Suggestions should remain reversible, and the full information should still be accessible. For this project, the most promising principle is therefore not an interface that constantly rearranges itself, but a stable structure with carefully limited adaptive areas.</p>



<p class="wp-block-paragraph">If adaptation is intended to reduce cognitive load, it must not create new uncertainty. Sufficient contrast, consistent controls, and user agency remain more important than novelty. The underlying system has to be stable first.</p>



<h2 class="wp-block-heading">What I learned from the process</h2>



<p class="wp-block-paragraph">Looking back at the period from March to August 2026, the design developed through three broad stages. The first established the functional structure through wireframes. The second introduced a strong but comparatively playful visual direction. The third refined that direction through collaboration, implementation, and feedback until the interface became calmer and more coherent.</p>



<p class="wp-block-paragraph">The process showed me that refinement is not simply the act of making a design more polished. It often requires changing the criteria by which the design is judged. Early in the project, I focused strongly on whether the screens had personality. Later, I evaluated whether that personality supported orientation, readability, and trust. The final direction is not less designed than the first one. It is more selective about where design becomes visible.</p>



<p class="wp-block-paragraph">Recurring feedback also proved valuable even with a small test group. The most important findings were fundamental issues such as text size and contrast. Repetition made them harder to dismiss as individual preference and turned them into priorities. The design collaboration added a dialogue between graphic expression and interaction requirements rather than a simple handover between disciplines.</p>



<p class="wp-block-paragraph">The current design should not be understood as a finished public product. More testing will be necessary on real devices and across different display settings. Accessibility checks must become continuous rather than a final review, and the adaptive interface idea will require careful prototyping.</p>



<p class="wp-block-paragraph">For now, the most important result is a clearer design foundation. The project has moved from a collection of functional screens toward a recognizable system with shared principles. It can remain personal without becoming visually noisy, and it can become more structured without losing its organic character.</p>



<p class="wp-block-paragraph">The complete application is not ready to be revealed, but the development process already offers a useful lesson: a calm interface is not created by simply removing elements or choosing quiet colors. It is created by deciding what deserves attention, testing whether users can recognize it, and refining every visual choice until personality and clarity support each other.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://mobile.fhstp.ac.at/ux/design/designing-a-calm-planning-experience-from-wireframes-to-a-coherent-visual-identity/">Designing a Calm Planning Experience: From Wireframes to a Coherent Visual Identity</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Building a Personal Planning App: From Interface Idea to Data-Driven iOS Prototype</title>
		<link>https://mobile.fhstp.ac.at/allgemein/building-a-personal-planning-app-from-interface-idea-to-data-driven-ios-prototype/</link>
		
		<dc:creator><![CDATA[Melanie Maier]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 07:37:26 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[swift]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15909</guid>

					<description><![CDATA[<p>Software projects often begin with a feature list. This one began with a feeling: everyday planning tools are everywhere, and yet personal organization still often feels fragmented. Calendars live in one place, tasks in another, reminders somewhere else, and the mental work of connecting them is left to the user. The goal of this project <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/building-a-personal-planning-app-from-interface-idea-to-data-driven-ios-prototype/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/building-a-personal-planning-app-from-interface-idea-to-data-driven-ios-prototype/">Building a Personal Planning App: From Interface Idea to Data-Driven iOS Prototype</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Software projects often begin with a feature list. This one began with a feeling: everyday planning tools are everywhere, and yet personal organization still often feels fragmented. Calendars live in one place, tasks in another, reminders somewhere else, and the mental work of connecting them is left to the user. The goal of this project was not simply to build another productivity app, but to explore how a planning interface could feel more coherent, calmer, and closer to the way people actually think about their days.</p>



<p class="wp-block-paragraph">The app is still in development, and many of its final ideas are intentionally not public yet. For that reason, this article does not reveal the complete product concept or all planned functionality. Instead, it focuses on the development process so far: how the project evolved from a SwiftUI interface prototype into a more structured iOS application with custom data models, persistent storage, reusable components, and first steps toward external calendar integration.</p>



<p class="wp-block-paragraph">At the beginning, the project was mostly visual and exploratory. The first question was not “Which database should this use?” or “How should synchronization work?” but “What should this feel like on a phone?” Since the app is meant to be used frequently and quickly, the interface had to be approachable without becoming decorative for its own sake. SwiftUI was a natural choice because it allowed fast iteration on layout, navigation, state, and component structure. Early work focused on core screens: a home view, overview pages, detail pages, and small reusable interface elements that could later become the visual language of the app.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Wireframes-1540x800.png" alt="" class="wp-image-15918" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Wireframes-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Wireframes-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>



<p class="wp-block-paragraph">One of the first lessons was that a planning app becomes complex faster than expected. Even if the user-facing idea sounds simple, the underlying structures are not. A calendar item is not just a title and a date. It may have a start and end time, an all-day state, a location, notes, tags, a source, an editability status, and possibly a connection to another system. A task is also more than a checkbox. It can belong to a list, have a due date, include notes, be marked as important, be connected to a reminder, or later need rules for rescheduling. Reminders introduce yet another rhythm, because they are not exactly tasks and not exactly events. They sit somewhere between intention and interruption.</p>



<p class="wp-block-paragraph">Because of that, the project moved relatively early from screen-building into model-building. Separate structures were created for calendars, events, lists, tasks, reminders, external sources, and calendar connections. This was an important shift. Instead of letting the UI define the data informally, the data model started to define what the interface could reliably express. Each object needed an identity, needed to be encodable, and needed to be flexible enough for future features without becoming vague. This part of the process was less visually exciting than building screens, but it made the rest of the application much more stable.</p>



<p class="wp-block-paragraph">The central data layer became an observable store that holds the current calendars, events, lists, tasks, reminders, and external connections. This store is used throughout the SwiftUI views via environment injection, which keeps the individual screens relatively focused. A home screen can ask for visible calendars, upcoming events, or incomplete tasks without owning all the logic itself. Detail pages can receive a selected object and rely on shared update and delete methods. This architecture is still lightweight, but it creates a clear boundary between application state and presentation.</p>



<p class="wp-block-paragraph">A useful turning point was implementing filtering and derived data. Once there were multiple entities in the store, the app needed answers to questions such as: Which events belong to this calendar? Which tasks belong to this list? Which events are upcoming? Which tasks are incomplete and still relevant? These may sound like small helper functions, but they changed how the app could be built. Instead of each screen duplicating filtering code, the store became the place where the application’s understanding of its data lived. That made the UI easier to read and helped reduce inconsistencies between screens.</p>



<p class="wp-block-paragraph">Another major step was persistence. In early prototypes, sample data is enough. It helps with layout and gives the app something to display. But a planning app cannot remain a prototype for long if data disappears every time it restarts. The current version stores a snapshot of the application data as JSON in the app’s documents directory. The snapshot includes the core collections and can be loaded again when the app starts. The saving process also keeps a backup file, so the app has a fallback if the primary file cannot be read.</p>



<p class="wp-block-paragraph">This persistence system is intentionally simple. It is not yet a large database layer, and that is partly deliberate. At this stage, JSON-based persistence makes the app easier to inspect, debug, and evolve. The project is still changing, and a lighter storage approach gives more freedom while the domain model continues to settle. At the same time, the persistence layer is separated from the store, so replacing or extending it later would not require rewriting the entire UI. This is one of the recurring themes of the project: avoid overengineering too early, but create enough structure that future changes do not become painful.</p>



<p class="wp-block-paragraph">Autosave introduced its own design questions. A planning app should not require the user to manually save after every small change. The current approach listens for changes across the main collections and saves the current snapshot after a short debounce. This means the app can react naturally to edits while avoiding excessive file writes. It also means the development process had to account for state changes that are not user edits, such as loading persisted data at launch. Small flags and guard conditions became necessary to prevent the app from immediately saving over freshly loaded state or treating internal setup as user activity.</p>



<p class="wp-block-paragraph">The interface also evolved significantly during this phase. The app now has a clearer structure of pages and components: overview views, detail views, card components, a navigation bar, headers, picker panels, floating action controls, and shared form elements. This componentization was not just about cleaner code. It also helped the app develop a consistent interaction style. Planning tools can easily become cluttered because they contain many object types and many possible actions. Reusable components make it easier to keep the experience predictable.</p>



<p class="wp-block-paragraph">One example is the creation flow. Adding something new should not feel like entering a completely different app. The current implementation uses a shared sheet for creating or editing different item types. It supports modes for events, tasks, and reminders, with separate draft objects and validation. This draft-based approach is important because forms are temporary by nature. A user can open a sheet, make changes, switch context, cancel, or save. Keeping draft state separate from the saved model avoids accidental writes and makes validation clearer.</p>



<p class="wp-block-paragraph">The form system also revealed how much detail is hidden inside “simple” input. Dates, times, optional fields, associations with calendars or lists, tags, icons, and reminder relationships all require careful handling. If these concerns are spread directly across the view code, the form quickly becomes difficult to maintain. By separating drafts, form rows, picker state, and saving logic, the app gained a structure that can grow without turning every new field into a cascade of fragile changes.</p>



<p class="wp-block-paragraph">Design-wise, the project has been moving toward a custom visual identity rather than relying entirely on default iOS components. Custom fonts, color assets, icons, rounded shapes, and card components give the app a more personal tone. This is not only aesthetic. For a planning tool, visual hierarchy matters. The user should be able to distinguish calendars, lists, upcoming items, actions, and details quickly. Colors and cards are not decoration here; they carry information and help reduce cognitive load.</p>



<p class="wp-block-paragraph">At the same time, building a custom interface in SwiftUI requires restraint. It is tempting to make every component unique, especially in a project that has a strong visual direction. But the more custom the interface becomes, the more responsibility the developer takes on for spacing, accessibility, responsiveness, and consistency. This has been one of the practical challenges of the project: finding the balance between a distinctive interface and a maintainable one. The current component structure is an attempt to make that balance explicit.</p>



<p class="wp-block-paragraph">The most technically demanding part so far has been external calendar integration. Local planning data is one thing; synchronizing with external systems is another. The app now contains service layers for Apple Calendar and Google Calendar, as well as a synchronization service that imports events into the app’s own model. This required thinking about authorization, external identifiers, read-only versus editable sources, date ranges, mapping between API objects and local models, and what should happen when external events change or disappear.</p>



<p class="wp-block-paragraph">Apple Calendar integration uses EventKit and must deal with platform-specific permission states. On newer iOS versions, access levels are more precise, so the app has to request and verify the correct kind of calendar access. The service can list available calendars and load events within a selected time range. These events are then mapped into the app’s internal event model, preserving information such as title, location, notes, URL, start and end date, all-day status, external identity, and sync metadata.</p>



<p class="wp-block-paragraph">Google Calendar integration is different because it goes through Google Sign-In and web API requests. This required handling OAuth scopes, restoring previous sign-in sessions, refreshing access tokens, making authenticated requests, decoding calendar lists and event responses, and converting Google’s date formats into local date values. All-day events need special handling because calendar APIs often represent them differently from timed events. These are the kinds of details that are easy to underestimate before implementation begins.</p>



<p class="wp-block-paragraph">The synchronization layer sits above the individual provider services. It loops through configured external calendar connections, loads events for each connection, imports them, tracks which external IDs were seen, updates sync timestamps, and reports failures. The store then upserts imported events instead of blindly appending them. This prevents duplicates and creates a place to handle conflicts. If a local event has pending changes and an external version arrives, the app can mark the situation as a conflict rather than silently overwriting data. Even though the full synchronization story is not finished, the current structure already reflects a key principle: user data should be treated carefully.</p>



<p class="wp-block-paragraph">This was one of the biggest conceptual lessons of the project. Synchronization is not just a technical feature. It is a trust feature. If users put their plans into an app, they need confidence that the app will not lose, duplicate, or unexpectedly modify important information. That means the code has to represent uncertainty. It needs states such as local-only, synced, pending local changes, conflict, or deleted externally. These states are not glamorous, but they are what make the difference between a demo and a tool people might rely on.</p>



<p class="wp-block-paragraph">Another lesson was that the app’s “domain” became clearer through implementation. At first, calendars, lists, tasks, and reminders may seem like familiar categories. But once they are modeled together, their relationships become more interesting. Some items belong to collections. Some can be associated with time. Some can be completed, others can only pass. Some are imported from outside and should not be edited locally. Some may later need richer rules. The development process has therefore been partly technical and partly analytical: understanding what each object means in the system.</p>



<p class="wp-block-paragraph">The current prototype also includes several navigation paths: a home view with upcoming information, calendar overviews and detail views, list overviews and detail views, event and task detail screens, and setup flows. This breadth created a new kind of challenge. Once the app had more than one or two screens, consistency became harder. A change in the model might affect a card, a detail page, a form, and a preview all at once. This is where reusable view components started to pay off. They made the app feel less like a set of separate screens and more like one coherent product.</p>



<p class="wp-block-paragraph">The project is still in an active development stage. There are visible signs of ongoing refactoring: components have been moved into clearer folders, global elements have been separated from list-specific and calendar-specific components, and some older file paths are being replaced by a more organized structure. This is a normal and healthy part of development. Early prototypes often grow organically. At some point, the structure has to catch up with the idea. The important part is not to make the architecture perfect immediately, but to keep improving it when the project’s shape becomes clearer.</p>



<p class="wp-block-paragraph">Looking back, the development so far can be described in phases. The first phase was interface exploration: building enough screens to understand the experience. The second phase was domain modeling: defining the objects the app actually needs. The third phase was state and persistence: making the app remember and update data reliably. The fourth phase was integration: connecting the local world of the app with external calendar systems. The current phase is consolidation: refining components, improving flows, reducing duplication, and preparing the project for more advanced behavior.</p>



<p class="wp-block-paragraph">For a student or early-stage software project, this progression is valuable because it shows how practical software development rarely follows a perfectly linear plan. The app did not begin with a complete architecture diagram and then simply fill in the pieces. Instead, each implementation step revealed the next architectural need. A form revealed the need for drafts. External calendars revealed the need for source metadata and sync states. Autosave revealed the need to distinguish loading from editing. Reusable cards revealed the need for stronger model relationships. The architecture emerged through contact with the problem.</p>



<p class="wp-block-paragraph">There is also a broader lesson about building products that are not ready to be fully disclosed. It can be difficult to talk about a project publicly when the most exciting parts are still private. But not every development story has to reveal the final product. It is possible to discuss the engineering process, the technical decisions, the mistakes avoided, and the problems encountered without giving away the complete concept. In some ways, this is more useful for an informatics audience. The real value is not only in what the app will eventually do, but in how the system is being shaped to make that possible.</p>



<p class="wp-block-paragraph">The next steps will likely focus on stability, refinement, and careful expansion. The persistence system will need to remain reliable as the data model grows. Synchronization will need more testing, especially around conflicts and edge cases. The interface will need continued polishing across different device sizes and user scenarios. Some flows that currently exist as early implementations will need to become more robust. And as the app moves closer to a publishable version, privacy, permissions, error handling, and user trust will become even more important.</p>



<p class="wp-block-paragraph">What makes this project interesting is that it sits at the intersection of design, data modeling, and everyday behavior. A planning app is not just a technical container for events and tasks. It is a tool that asks to be invited into a user’s routine. That creates a high bar: the app has to be useful without being noisy, structured without being rigid, and personal without becoming confusing. Reaching that balance takes iteration.</p>



<p class="wp-block-paragraph">So far, the development has already moved beyond a simple prototype. The app has a working SwiftUI foundation, a growing design system, structured models, persistent local data, reusable creation flows, and initial external calendar synchronization. More importantly, it has a clearer sense of direction. The final product is not ready to be revealed yet, but the development process has already shown what kind of challenge this is: not merely building screens, but building a coherent planning environment one careful layer at a time.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/building-a-personal-planning-app-from-interface-idea-to-data-driven-ios-prototype/">Building a Personal Planning App: From Interface Idea to Data-Driven iOS Prototype</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Projekt WS25 &#124; MixMatch (Fortsetzung)</title>
		<link>https://mobile.fhstp.ac.at/allgemein/projekt-ws25-mixmatch-fortsetzung/</link>
		
		<dc:creator><![CDATA[Andreas Kaiser]]></dc:creator>
		<pubDate>Mon, 02 Mar 2026 17:16:26 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Studium]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15368</guid>

					<description><![CDATA[<p>Um mein Projekt “MixMatch” näher in die Richtung production-ready Zustand zu bringen wurde das 3. Semester von mir genutzt, nahtlos an den zuvor vorhandenen Stand der Entwicklung anzuschließen. Im Semester habe ich mich im wesentlichen darauf fokussiert, Community Features, wie Sterne-Bewertungen und Kommentier- bzw. Antwortfunktion, in meine Nativescript-App zu integrieren und deutlich mehr Zeit in <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/projekt-ws25-mixmatch-fortsetzung/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/projekt-ws25-mixmatch-fortsetzung/">Projekt WS25 | MixMatch (Fortsetzung)</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Um mein Projekt “MixMatch” näher in die Richtung production-ready Zustand zu bringen wurde das 3. Semester von mir genutzt, nahtlos an den zuvor vorhandenen Stand der Entwicklung anzuschließen.</p>



<p class="wp-block-paragraph">Im Semester habe ich mich im wesentlichen darauf fokussiert, Community Features, wie Sterne-Bewertungen und Kommentier- bzw. Antwortfunktion, in meine Nativescript-App zu integrieren und deutlich mehr Zeit in Bugfixing zu investieren. Nebenbei wurde stellenweise das Design weiter optimiert, sowie das Fehlerhandling überarbeitet. Zur Abrundung wurde im Projektabschnitt eine exportierbare Einkaufliste für Zutaten, die der/die User:in braucht, um die Rezepte nachzumachen, integriert.</p>



<h2 class="wp-block-heading"><strong>Neuerungen seit dem letzten Semester</strong></h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img decoding="async" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/03/Screenshot_20260301_232048.png" alt="" class="wp-image-15782"/></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img decoding="async" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/03/Screenshot_20260302_003203.png" alt="" class="wp-image-15787"/></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img decoding="async" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/03/Screenshot_20260301_232236.png" alt="" class="wp-image-15784"/></figure>
</div>
</div>



<ul class="wp-block-list">
<li><strong>Filteroptionen in der Rezeptliste</strong></li>
</ul>



<p class="wp-block-paragraph">Der größte strukturelle Umbau fand in der Rezeptliste statt. Bisher wurden die Rezepte einfach als rohe Liste angezeigt, ohne Möglichkeit zur Filterung. Jetzt gibt es eine eigene Suchleiste mit Autocomplete-Vorschlägen der gefilterten Drinks, eine alphabetische Sortierung mit Drink-Nummer pro Karte, sowie einen Toggle-Filter für Signature Drinks.</p>



<ul class="wp-block-list">
<li><strong>Kommentar-Sektion bei den Recipes</strong></li>
</ul>



<p class="wp-block-paragraph">Das Herzstück des Projektes war die Erweiterung, dass jedes Rezept nun eine vollwertige Community-Section hat. User:innen können Kommentare mit Sternebewertung hinterlassen, auf Kommentare anderer antworten und eigene Kommentare wieder löschen. Die Bewertungen fließen in eine Durchschnittsbewertung ein, die prominent im Header der Rezeptkarte angezeigt wird. Die gesamte Kommunikation läuft in Echtzeit über WebSockets.</p>



<ul class="wp-block-list">
<li><strong>Benötigte Zutaten einer Einkaufsliste hinzufügen</strong></li>
</ul>



<p class="wp-block-paragraph">Bisher wurden alle nicht angegebenen Zutaten bei der Hauptsuche automatisch gesammelt und global in meinem Code zwischengespeichert. Das wurde grundlegend über ein Einkaufslisten-Feature überarbeitet: Pro Rezept kann der/die Nutzer:in nun selbst entscheiden, ob er/sie die fehlenden Zutaten zur Einkaufsliste hinzufügen möchte. Fehlende Zutaten werden in der Zutatenliste farblich in Orange hervorgehoben. Ein einzelner Button pro Rezept überträgt dann gezielt nur die fehlenden Zutaten in die Einkaufsliste. Die Einkaufsliste selbst unterstützt den Export als PDF über den nativen Android PrintManager sowie im CSV-Format.</p>



<p class="wp-block-paragraph">Neben diesen Änderungen konnten viele Bugs behoben werden. Speziell einige Bugs, die die Funktionalität rund um die Erstellung von “Signature Drinks” (anlegen/löschen) als auch den Umgang mit gekennzeichneten Favoriten-Rezepten, eingeschränkt haben, existieren nicht mehr.</p>



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



<p class="wp-block-paragraph">Der Großteil an Technologien ist gleich geblieben. Im Frontend setze ich weiterhin auf NativeScript Angular bzw. Tailwind für das Design und im Backend SpringBoot. Das Backend habe ich dieses Semester erstmalig über den Online-Service Railway gehostet. Dazugekommen sind vor allem die WebSocket-Bibliothek <code>@stomp/stompjs</code> im Frontend sowie die entsprechende Spring WebSocket-Abhängigkeit im Backend.</p>



<p class="wp-block-paragraph">Für die Kommentar-Funktion war von Anfang an klar, dass klassische HTTP-Requests nicht ausreichen , sonst wäre ein ständiges manuelles Aktualisieren notwendig gewesen, um neue Kommentare zu sehen. Die Wahl fiel auf WebSockets mit STOMP, einem einfachen Messaging-Protokoll das auf WebSocket aufsetzt und ein Publish-Subscribe-Modell ermöglicht. Im Spring Boot Backend wird dabei ein Message-Broker konfiguriert der eingehende Nachrichten an alle Subscriber des jeweiligen Rezept-Topics weiterleitet. Jedes Rezept hat seinen eigenen Kanal, zum Beispiel <code>/topic/recipe/42/comments</code>. Nur Nutzer:innen die gerade dieses Rezept offen haben, empfangen die Kommentar, die zu diesem Rezept abgegeben wurden. Der Controller nimmt neue Kommentare entgegen, speichert sie und schickt sie sofort an alle aktiven Subscriber:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: java; title: ; notranslate">
@MessageMapping(&quot;/comments/create&quot;)
public void createComment(CreateCommentRequestDto request, Principal principal) {
    User author = userRepository.findByUsername(principal.getName())...;
    CommentResponseDto saved = commentService.createComment(request, author);
    messagingTemplate.convertAndSend(
        &quot;/topic/recipe/&quot; + request.getRecipeId() + &quot;/comments&quot;, 
        saved
    );
}
</pre></div>


<p class="wp-block-paragraph">Im Frontend übernimmt ein dedizierter <code>CommentWebSocketService</code> die gesamte Verbindungslogik. Er verwendet die <code>@stomp/stompjs</code> Bibliothek, schickt den JWT-Token beim Verbindungsaufbau mit und subscribt auf den zum Rezept passenden Topic-Kanal:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: java; title: ; notranslate">
this.stompClient = new Client({
    webSocketFactory: () =&gt; new WebSocket(`wss://...railway.app/ws`),
    connectHeaders: { Authorization: `Bearer ${this.authToken}` },
    reconnectDelay: 5000,
});
 
this.stompClient.onConnect = () =&gt; {
    this.stompClient.subscribe(
        `/topic/recipe/${this.recipeId}/comments`,
        (message) =&gt; {
            const comment = JSON.parse(message.body);
            onCommentReceived(comment);
        }
    );
};
</pre></div>


<h2 class="wp-block-heading"><strong>Herausforderungen &amp; Learning(s) daraus</strong></h2>



<p class="wp-block-paragraph">Die größte Herausforderung des Semesters waren eindeutig die WebSockets. Theoretisch klingt es simpel (Verbindung öffnen und Nachrichten empfangen), jedoch in der Praxis gab es einige Hürden. Zuerst die Authentifizierung: anders als bei normalen HTTP-Requests musste der JWT-Token über die STOMP <code>connectHeaders</code> mitgeschickt und im Backend extra validiert werden. Dann das Problem mit inaktiven Verbindungen, denn ohne der sogenannten “Heartbeat-Konfiguration” auf beiden Seiten kamen Nachrichten irgendwann einfach nicht mehr an (Fehlermeldungen wurden nicht geworfen). Zu guter Letzt das Aufräumen der Verbindungen, denn ohne explizites <code>disconnect()</code> blieben im Hintergrund immer mehr aktive Verbindungen offen.</p>



<p class="wp-block-paragraph">Was das Aufräumen so schwierig gemacht hat, war der Pager, mit dem man zwischen den Rezepten swipen kann. NativeScript’s Pager-Komponente erstellt alle Rezept-Items gleichzeitig beim Laden, bei 14 Rezepten also sofort 14 WebSocket-Verbindungen und 14 HTTP-Requests, obwohl der/die Nutzer:in nur ein einziges Rezept sieht. Noch dazu wird <code>ngOnDestroy</code> beim Wischen zwischen den Items nicht zuverlässig aufgerufen, weil der Pager seine Views intern recycelt statt sie wirklich zu zerstören. Dadurch hat die Cleanup-Logik nie gefeuert.</p>



<p class="wp-block-paragraph">Die Lösung war letztlich ein Umdenken: statt auf <code>ngOnDestroy</code> zu vertrauen, steuert jetzt ein Flag, ob die Kommentar-Sektion überhaupt gerendert wird. Sobald der Nutzer wegwischt, verschwindet die Komponente via <code>*ngIf</code> aus dem DOM, damit das Cleanup zuverlässig durchläuft. Das wesentliche Learning dabei, war ein gut ausgebautes Debugging zu haben.</p>



<h2 class="wp-block-heading"><strong>Fazit und zukünftige TODOs</strong></h2>



<p class="wp-block-paragraph">In diesem Projektabschnitt konnte ich mich erstmalig herausfordernd damit befassen, wie WebSockets technisch umgesetzt werden. Das war gleichzeitig eines der interessantesten und aufwändigsten Themen des Semesters. Die vielen Debugging-Sessions haben mich aber auch am meisten weitergebracht. Rückblickend bin ich sehr zufrieden damit, was ich mir vorgenommen hatte auch tatsächlich vollständig umgesetzt zu haben. Gerade das Bugfixing war diesmal besonders aufwändig, hat aber mit großem Erfolg geendet und manche Features meiner App brauchbarer gemacht.</p>



<p class="wp-block-paragraph">An diesen Dingen sollte nun weitergearbeitet werden: Performance-seitig gibt es noch Luft nach oben, sowohl beim initialen Laden als auch bei den Screen-Wechseln merkt man stellenweise noch Verzögerungen die es zu optimieren gilt. Auch das Design ist noch nicht wirklich durchgängig einheitlich, was ich in einem nächsten Schritt konsequenter angehen möchte. Dazu kommt, dass ich bisher kaum echtes User-Feedback eingeholt habe, das soll sich ändern. Auf technischer Seite fehlen noch automatisierte Tests, die zur noch besseren Stabilität der App beitragen sollen. Schlussendlich wäre das große Ziel die App veröffentlichen zu können.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Beitragsbild</strong>: dieses wurde mittels Einsatz von KI erzeugt</p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/projekt-ws25-mixmatch-fortsetzung/">Projekt WS25 | MixMatch (Fortsetzung)</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Projekt &#124; Timelapse Android App</title>
		<link>https://mobile.fhstp.ac.at/development/projekt-timelapse-android-app/</link>
		
		<dc:creator><![CDATA[David Grünberger]]></dc:creator>
		<pubDate>Thu, 26 Feb 2026 10:19:46 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Jetpack Compose]]></category>
		<category><![CDATA[Material Design]]></category>
		<category><![CDATA[mobile]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15691</guid>

					<description><![CDATA[<p>Im Rahmen des Semesterprojekts im 3. Semester der Masterklasse Mobile habe ich die Android-App &#8220;Timelapse&#8221; entwickelt. Die Idee dahinter: Aus vielen einzelnen Momentaufnahmen wird automatisch ein visueller Zeitstrahl – als Video, das langfristige Veränderungen sichtbar macht. Egal ob Bartwachstum, Fitness-Progress oder das Wachstum einer Zimmerpflanze: Timelapse hilft dabei, diese Reise festzuhalten. Ziel des Projekts war ein alltagstauglicher MVP, der den kompletten Ablauf abdeckt: vom Erstellen <a class="read-more" href="https://mobile.fhstp.ac.at/development/projekt-timelapse-android-app/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/projekt-timelapse-android-app/">Projekt | Timelapse Android App</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Im Rahmen des Semesterprojekts im 3. Semester der Masterklasse Mobile habe ich die Android-App &#8220;Timelapse&#8221; entwickelt. Die Idee dahinter: Aus vielen einzelnen Momentaufnahmen wird automatisch ein visueller Zeitstrahl – als Video, das langfristige Veränderungen sichtbar macht. Egal ob Bartwachstum, Fitness-Progress oder das Wachstum einer Zimmerpflanze: Timelapse hilft dabei, diese Reise festzuhalten. Ziel des Projekts war ein alltagstauglicher MVP, der den kompletten Ablauf abdeckt: vom Erstellen eines Projekts über tägliche Erinnerungen und eine übersichtliche Tage-Ansicht bis hin zur fertigen Video-Montage, die sich teilen oder archivieren lässt.</p>



<h2 class="wp-block-heading">Worum es in der&nbsp;App geht</h2>



<p class="wp-block-paragraph">Im Kern funktioniert Timelapse wie ein&nbsp;visuelles&nbsp;Tagebuch:</p>



<ul class="wp-block-list">
<li>Nutzer:innen legen Projekte an (z. B. „Daily Selfie“ oder „Zimmerpflanze“).</li>



<li>Die App erinnert regelmäßig daran, neue Fotos aufzunehmen.</li>



<li>Alle Bilder werden zeitlich geordnet, mit Datum und optionalen Kommentaren gespeichert.</li>



<li>Auf einer kompakten Übersicht sieht man, wann man etwas aufgenommen hat, welche Tage besonders wichtig waren und wie sich das Projekt über Wochen und Monate entwickelt.</li>



<li>Aus dieser Sammlung erzeugt Timelapse auf Knopfdruck ein Zeitraffervideo, das die Geschichte des Projekts in wenigen Sekunden erzählt.</li>
</ul>



<h2 class="wp-block-heading">Zentrale&nbsp;Funktionen&nbsp;in&nbsp;Kürze</h2>



<ul class="wp-block-list">
<li><strong>Projektorganisation:</strong> Mehrere parallele Timelapse-Projekte mit Titel, Beschreibung und individuellen Einstellungen.</li>



<li><strong>Visuelle Timeline:</strong> Eine kombinierte Wochen- und Listenansicht zeigt, welche Tage schon dokumentiert sind und welche Lücken es noch gibt.</li>



<li><strong>Erinnerungen:</strong> Konfigurierbare Benachrichtigungen, damit die tägliche Aufnahme zur Routine wird und die Timeline nicht abreißt.</li>



<li>F<strong>avoriten &amp; Notizen:</strong> Einzelne Tage können hervorgehoben und mit kurzen Kommentaren versehen werden – etwa um Meilensteine oder besondere Momente zu markieren.</li>



<li><strong>Automatische Video-Montage:</strong> Die App erstellt aus den Bildern ein Video, berücksichtigt Ausrichtung, Datum, optionales Wasserzeichen und Kommentare und bietet Konfigurationsmöglichkeiten für Qualität oder Textstil.</li>
</ul>



<figure class="wp-block-gallery has-nested-images columns-4 wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img decoding="async" data-id="15763" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/Screenshot_20260226_122653_Timelapse.jpg" alt="" class="wp-image-15763"/></figure>



<figure class="wp-block-image size-full"><img decoding="async" data-id="15765" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/Screenshot_20260226_122559_Timelapse.jpg" alt="" class="wp-image-15765"/></figure>



<figure class="wp-block-image size-full"><img decoding="async" data-id="15764" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/Screenshot_20260226_122619_Timelapse.jpg" alt="" class="wp-image-15764"/></figure>



<figure class="wp-block-image size-full"><img decoding="async" data-id="15766" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/02/Screenshot_20260226_122700_Timelapse.jpg" alt="" class="wp-image-15766"/></figure>
<figcaption class="blocks-gallery-caption wp-element-caption"><strong>Abb. 1: App Screenshots</strong></figcaption></figure>



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



<p class="wp-block-paragraph">Die&nbsp;App ist&nbsp;als&nbsp;native&nbsp;Android-Anwendung mit Jetpack Compose&nbsp;umgesetzt und&nbsp;nutzt&nbsp;moderne&nbsp;Android-APIs sowie eine&nbsp;klare&nbsp;Schichtung&nbsp;zwischen&nbsp;UI, Logik&nbsp;und Medienverarbeitung.</p>



<ul class="wp-block-list">
<li><strong>UI: Jetpack Compose + Material 3</strong>
<ul class="wp-block-list">
<li>Alle Screens (Projektliste, Details, Dialoge, Konfiguration) sind vollständig in Compose realisiert.</li>



<li>Material-3-Komponenten wie LargeFlexibleTopAppBar, Listen, Cards und Dialoge sorgen für ein konsistentes Look &amp; Feel.</li>



<li>Ein zentrales TimelapseTheme verwaltet App-Theme (Light/Dark), Seed-Farbe und den Palette-Stil.</li>
</ul>
</li>



<li><strong>Material 3 Expressive &amp; Material You</strong>
<ul class="wp-block-list">
<li>Die App nutzt Material 3 Expressive, um eine lebendige, charakterstarke Farb- und Typografie-Sprache umzusetzen – passend zu einer App, die persönliche Veränderungen dokumentiert.</li>



<li>Über einen integrierten Color Picker wählen Nutzer:innen eine eigene Akzentfarbe.</li>



<li>Aus dieser Seed-Farbe wird mit Material You ein komplettes Farbschema generiert, das sich konsistent über die gesamte App zieht.</li>



<li>Dadurch wirkt Timelapse auf jedem Gerät persönlich, bleibt aber immer klar strukturiert und gut lesbar – unabhängig davon, ob Light- oder Dark-Mode aktiv ist.</li>
</ul>
</li>



<li><strong>Video-Montage &amp; Bildverarbeitung</strong>
<ul class="wp-block-list">
<li>Die Montage-Logik läuft in einem eigenen Modul:</li>



<li>Bilder werden anhand ihrer EXIF-Daten korrekt ausgerichtet.</li>



<li>Ein Canvas setzt die Frames zusammen, ergänzt Texte (Datum, Kommentare, Wasserzeichen) und kümmert sich um Hintergrundfarbe und Zensurflächen.</li>



<li>Ein Muxer erzeugt daraus ein MP4-Video, gesteuert über Kotlin Flows, die den Fortschritt an die UI melden.</li>



<li>So entsteht aus einer losen Sammlung von Bildern ein stimmiges Timelapse-Video, ohne dass externe Tools nötig sind.</li>
</ul>
</li>
</ul>



<h2 class="wp-block-heading">Material&nbsp;3 Expressive&nbsp;&amp; Material You im&nbsp;Einsatz</h2>



<p class="wp-block-paragraph">Ein großer&nbsp;Fokus&nbsp;des&nbsp;Projekts lag&nbsp;auf einer&nbsp;modernen, adaptiven&nbsp;UI, die sich&nbsp;nach&nbsp;den&nbsp;Nutzer:innen richtet:</p>



<ul class="wp-block-list">
<li><strong>Dynamische Farbwelten</strong>
<ul class="wp-block-list">
<li>Durch den Seed-Color-Ansatz wirkt die App nicht wie ein statisch durchgestyltes Produkt, sondern wie ein Rahmen, der sich der jeweiligen Geschichte anpasst.</li>



<li>Projekte mit emotionalem Kontext (z. B. Schwangerschaft, Beziehungen, erste Wohnung) profitieren von den kräftigen, expressiven Paletten, die Material 3 bereitstellt.</li>
</ul>
</li>



<li><strong>Einheitliche, weiche Formsprache</strong>
<ul class="wp-block-list">
<li>Großzügige Rundungen (z. B. extra große Card-Shapes in Dialogen), expressive Typografie und bewusst eingesetzte Icons unterstützen den Tagebuch-Charakter der App.</li>



<li>Die App verzichtet auf überladene UI-Elemente und setzt auf Ruhe, Klarheit und Fokus – wichtig, wenn man sich über Monate immer wieder mit derselben Oberfläche beschäftigt.</li>
</ul>
</li>



<li><strong>Konsistentes Theming</strong>
<ul class="wp-block-list">
<li>Alle Bausteine – von Erfassungsdialogs über Erinnerungs-Settings bis hin zu Fortschrittsanzeigen bei Scans und Montage – hängen am gleichen Theme.</li>



<li>Änderungen an Theme, Palette oder Seed-Farbe greifen sofort durch, ohne dass einzelne Screens speziell angepasst werden müssen.</li>
</ul>
</li>
</ul>



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



<ul class="wp-block-list">
<li><strong>Balance zwischen Einfachheit und Kontrolle</strong>
<ul class="wp-block-list">
<li>Nutzer:innen sollen einerseits „einfach nur“ ein Timelapse-Video erstellen können, andererseits genug Einstellmöglichkeiten für Qualität, Text, Stabilisierung und Privatsphäre haben.</li>



<li>Ein wichtiger Lernpunkt war, die Komplexität hinter klaren Dialogen und wenigen, gut erklärten Optionen zu verstecken.</li>
</ul>
</li>



<li><strong>Stabile, angenehme Timelapse-Videos</strong>
<ul class="wp-block-list">
<li>Kleine Fehler bei Skalierung oder Matrix-Transformation führen schnell zu Sprüngen oder abgeschnittenen Bereichen – hier war viel Feintuning nötig.</li>
</ul>
</li>



<li><strong>Durchgängiges Theming mit Material 3 / Material You</strong>
<ul class="wp-block-list">
<li>Seed-Farben, dynamische Paletten und unterschiedliche Palettenstile (z. B. Expressive) lassen sich mächtig kombinieren – aber nur, wenn das Theming-Konzept von Anfang an klar definiert ist.</li>



<li>Die wichtigste Erkenntnis: Ein zentrales Theme-Objekt vereinfacht langfristig alle Entscheidungen rund um Farben, Typografie und Component-Styling.</li>
</ul>
</li>
</ul>



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



<p class="wp-block-paragraph">Timelapse war für mich ein Projekt, in dem sich User Experience, modernes Android-Design und Medienverarbeitung sehr gut ergänzt haben. Die App zeigt, wie sich mit Jetpack Compose, Material 3 Expressive und Material You eine Oberfläche bauen lässt, die technisch anspruchsvolle Abläufe (zB. Videomontage) hinter einem einfachen, persönlichen Nutzungserlebnis versteckt. Besonders spannend war zu sehen, wie stark sich die Wahrnehmung der App ändert, wenn man eine eigene Farbwelt definieren kann und diese sich konsequent durch alle Screens zieht. In zukünftigen Schritten möchte ich die App um Themen wie Musik, Export-Presets und umfangreichere Sharing-Optionen erweitern – immer mit dem Ziel, den Kern beizubehalten: Veränderung sichtbar machen, ohne dass sich der Aufwand danach anfühlt.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/projekt-timelapse-android-app/">Projekt | Timelapse Android App</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
