<?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>Allgemein Archives - Mobile USTP MKL</title>
	<atom:link href="https://mobile.fhstp.ac.at/category/allgemein/feed/" rel="self" type="application/rss+xml" />
	<link>https://mobile.fhstp.ac.at/category/allgemein/</link>
	<description>Die &#34;Mobile Forschungsgruppe&#34; der USTP, sie  sammelt hier alles zu den Themen Design, UX und Entwicklung mobiler Applikationen</description>
	<lastBuildDate>Thu, 17 Sep 2026 09:46:03 +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>Allgemein Archives - Mobile USTP MKL</title>
	<link>https://mobile.fhstp.ac.at/category/allgemein/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Your AI Text Now Has a Hidden Fingerprint</title>
		<link>https://mobile.fhstp.ac.at/allgemein/your-ai-text-now-has-a-hidden-fingerprint/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/your-ai-text-now-has-a-hidden-fingerprint/#respond</comments>
		
		<dc:creator><![CDATA[Sander Hahn]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 09:46:03 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[watermark]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15969</guid>

					<description><![CDATA[<p>If you&#8217;ve used Claude recently, your text may carry a signature you cannot see. On August 14, 2026, Anthropic announced that Claude will watermark all the text its generating. But not only Anthropic is implementing watermaks: it&#8217;s one of about 190 companies that signed the EU&#8217;s Code of Practice on AI-generated content. Why now The <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/your-ai-text-now-has-a-hidden-fingerprint/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/your-ai-text-now-has-a-hidden-fingerprint/">Your AI Text Now Has a Hidden Fingerprint</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">If you&#8217;ve used Claude recently, your text may carry a signature you cannot see. On August 14, 2026, Anthropic announced that Claude will watermark all the text its generating. But not only Anthropic is implementing watermaks: it&#8217;s one of about 190 companies that signed the EU&#8217;s Code of Practice on AI-generated content.</p>



<h2 class="wp-block-heading">Why now</h2>



<p class="wp-block-paragraph">The main reason is of course regulation. <strong>Article 50 of the EU AI Act</strong> has applied since <strong>August 2, 2026</strong>. It requires AI providers to mark generated content in a machine-readable way, so it can be decteted more easily. This includes any company with EU users, not just European ones. Fines can reach €15M or 3% of global turnover. Similary, California&#8217;s SB 942 takes effect on the same date and requires hidden disclosures from providers with more than a million users in the state. Because two major markets have the same rule starting on the same day, AI providers now have to comply.</p>



<h2 class="wp-block-heading">How it works</h2>



<p class="wp-block-paragraph">A language model guesses one word at a time when writing and it often has more than one equally good options for the next word. After <em>&#8220;The weather today was cold and…&#8221;</em>, both &#8220;overcast&#8221; and &#8220;grey&#8221; fit. Normally a random number generator picks between them.</p>



<p class="wp-block-paragraph">Claude uses SynthID-Text, a method developed by Google DeepMind and it replaces that random pick with a rule based system that uses secret key and the words that came just before. With a small text it&#8217;s not as efficient but with over hundreds of words, though, it builds a statistical pattern that a detector with the key can measure.</p>



<p class="wp-block-paragraph">According to Anthropic:</p>



<ul class="wp-block-list">
<li><strong>Quality doesn&#8217;t change.</strong> The model only chooses among options it already rated as equally good and Google DeepMind&#8217;s testing found no significant difference in user ratings.</li>



<li><strong>Users pay nothing extra.</strong> The watermark adds no extra tokens.</li>



<li><strong>The watermark contains nothing about the user.</strong> It can&#8217;t be traced to a person, an organization or a chat.</li>
</ul>



<p class="wp-block-paragraph"><strong>Code</strong> gets very little watermarking, since there&#8217;s rarely a choice between equally good options. <strong>Images</strong> get <strong>C2PA</strong> metadata instead: a signed record that Claude was involved but a screenshot or re-save can strip it and Anthropic is also adding watermarks to older Claude models over the coming months.</p>



<h3 class="wp-block-heading">What it can&#8217;t do</h3>



<ul class="wp-block-list">
<li><strong>Short or factual text</strong> gives a weak signal, because there are few word choices to use the pattern.</li>



<li><strong>Editing weakens it.</strong> Copy paste keeps the watermark of couse but heavy editing weakens it and a full rewrite can even remove it.</li>



<li><strong>It can&#8217;t show authorship.</strong> It can&#8217;t tell whether Claude wrote a piece or only enhanced it.</li>



<li><strong>Common AI detectors can&#8217;t read it.</strong> GPTZero and Turnitin are still guessing from writing style. The real detection API is in private preview for regulators, researchers, media, schools and fact-checkers.</li>
</ul>



<h2 class="wp-block-heading">What to do about it</h2>



<p class="wp-block-paragraph">If you&#8217;re a freelancer or run a studio that uses AI in client work, stop treating AI use as something to hide. Write a clear disclosure policy that says when and how clients learn AI was involved and put it in your contracts. Now that AI involvement can be checked, being open about it costs you nothing and getting caught hiding it can cost a lot.</p>



<p class="wp-block-paragraph">Watermarks won&#8217;t end misinformation and a determined person can still get around them. But they change the default: most AI text will now carry a quiet signal of where it came from.</p>



<p class="wp-block-paragraph">Sources:<br><br></p>



<ul class="wp-block-list">
<li><a href="https://www.layer3labs.io/guides/ai-watermarking">https://www.layer3labs.io/guides/ai-watermarking</a></li>



<li><a href="https://www.anthropic.com/news/claude-text-watermark">https://www.anthropic.com/news/claude-text-watermark</a></li>
</ul>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/your-ai-text-now-has-a-hidden-fingerprint/">Your AI Text Now Has a Hidden Fingerprint</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/your-ai-text-now-has-a-hidden-fingerprint/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Designing OnTime V2 with Claude Design</title>
		<link>https://mobile.fhstp.ac.at/allgemein/designing-ontime-v2-with-claude-design/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/designing-ontime-v2-with-claude-design/#respond</comments>
		
		<dc:creator><![CDATA[Sander Hahn]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 09:37:23 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI Agents]]></category>
		<category><![CDATA[claude]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[design]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15990</guid>

					<description><![CDATA[<p>When I planned OnTime V2, my planning doc listed Figma as the design tool and I set aside 40 to 60 hours for design alone. In the end I didn&#8217;t open Figma at all. I designed the whole redesign in Claude Design. This article covers why I switched, how it went and where the tool <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/designing-ontime-v2-with-claude-design/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/designing-ontime-v2-with-claude-design/">Designing OnTime V2 with Claude Design</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">When I planned OnTime V2, my planning doc listed Figma as the design tool and I set aside 40 to 60 hours for design alone. In the end I didn&#8217;t open Figma at all. I designed the whole redesign in <strong>Claude Design</strong>. This article covers why I switched, how it went and where the tool reached its limits.</p>



<h2 class="wp-block-heading">Why not Figma or Canva?<br></h2>



<p class="wp-block-paragraph">All three big design tools now have AI. <strong>Figma</strong> puts it inside a professional canvas and coding agents can even design directly in your files. <strong>Canva AI 2.0</strong> creates layered, editable designs from a conversation. It&#8217;s great for marketing material, but it isn&#8217;t built for app UI.</p>



<p class="wp-block-paragraph">For OnTime, the question was simple: <strong>who is the designer on this project?</strong> I&#8217;m a solo developer. I had a design system in Figma to build on but I wanted something new. Claude Design can read images and design or even codebases and extract its colors, typography and components, so it was an easy choice.</p>



<h2 class="wp-block-heading">The start</h2>



<p class="wp-block-paragraph">V1 already had parts I wanted to keep, like the week calendar with drag-to-create entries and the live recorder. A new look wasn&#8217;t the only reason I decided to design a new UI. It also needed to fit a much bigger app around that core: workspaces, roles, invoices and bank reconciliation.</p>



<p class="wp-block-paragraph">So I didn&#8217;t start with a blank prompt but I gave Claude Design my previous design and it built a design system from them. Then I asked for the new screens. It made the iteration faster but it also needed a lot of help finding the correct design. It was by far not a single-prompt-execution and it took a lot of trial and error to get to a useable state.</p>



<ul class="wp-block-list">
<li><strong>Overview</strong>: V1&#8217;s overview had bar and pie charts. For V2, the overview got more animated stat cards, an activity heatmap and a project split.</li>



<li><strong>Calendar</strong>: This screen changed the least. The work here was mostly styling it to the new design and adding a new entry design so it&#8217;s more compatible for multi-user support. </li>



<li><strong>Table pages</strong>: The table pages consist (well) just pages, so the main thing was to add the new design layout and archivable entries with a switch.</li>



<li><strong>Notifications</strong>: Funnily enough, this page was the hardest to design because the plain table design didn&#8217;t feel right. I decided to use cards for each notification with views for read and unread messages.</li>



<li><strong>Invoices and payment review</strong>: These screens were new, so there was nothing from V1 to copy. But since it was also one of the last pages I got to, it was easier to find a fitting design.</li>
</ul>



<h2 class="wp-block-heading">From design to code<br></h2>



<p class="wp-block-paragraph">The implementation took the longest to do because I rebuilt everything by hand in React. Claude Design lets you export your website as code but without any framework. I could&#8217;ve moved around it to let Claude generate everything but I wanted to do the programming side on my own. The mobile shell sits behind its own build flag in the app so switching the flag for testing on desktop was easy to do.</p>



<h2 class="wp-block-heading">What worked, what didn&#8217;t<br></h2>



<p class="wp-block-paragraph"><strong>What worked:</strong></p>



<ul class="wp-block-list">
<li>Exploring was nearly free. I tried a lot of directions for the design and the different pages before settling on one.</li>



<li>The design system stayed mostly consistent across screens without me policing it.</li>
</ul>



<p class="wp-block-paragraph"><strong>What didn&#8217;t:</strong></p>



<ul class="wp-block-list">
<li>The spacing not always stayed consistent.</li>



<li>Not explaining your idea in detail leads to disappointing results.</li>



<li>Design may look generic.</li>
</ul>



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



<p class="wp-block-paragraph">For a solo developer, the design phase used to mean switching tools: design in Figma, then translate it into code by hand. With Claude Design, but now you can make Claude do the heavy lifting. Even though I decided to implement the design myself in code, it designing of the actual website was way faster and I was able to test a lot of different directions. The decisions stayed with me: what gets attention first, what stays from V1, what a finished page should look like. Claude did the designing and I made the design decisions.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1540" height="800" data-id="15997" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211138-1540x800.png" alt="" class="wp-image-15997" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211138-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211138-770x400.png 770w" sizes="(max-width: 1540px) 100vw, 1540px" /></figure>



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



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



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1540" height="800" data-id="15998" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211219-1540x800.png" alt="" class="wp-image-15998" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211219-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211219-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="15995" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211227-1-1540x800.png" alt="" class="wp-image-15995" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211227-1-1540x800.png 1540w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-211227-1-770x400.png 770w" sizes="auto, (max-width: 1540px) 100vw, 1540px" /></figure>
</figure>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/designing-ontime-v2-with-claude-design/">Designing OnTime V2 with Claude Design</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/designing-ontime-v2-with-claude-design/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OnTime V2</title>
		<link>https://mobile.fhstp.ac.at/allgemein/ontime-v2/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/ontime-v2/#respond</comments>
		
		<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 loading="lazy" 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="auto, (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>
					
					<wfw:commentRss>https://mobile.fhstp.ac.at/allgemein/ontime-v2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Creating your own custom Agent Harness like Claude Code and why it matters</title>
		<link>https://mobile.fhstp.ac.at/development/ai-agent-harness-claude-code/</link>
					<comments>https://mobile.fhstp.ac.at/development/ai-agent-harness-claude-code/#respond</comments>
		
		<dc:creator><![CDATA[Jakob Laschober]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 06:50:00 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Agent Harness]]></category>
		<category><![CDATA[AI Agents]]></category>
		<category><![CDATA[AI Automation]]></category>
		<category><![CDATA[AI Development]]></category>
		<category><![CDATA[AI Memory Management]]></category>
		<category><![CDATA[Anthropic]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Generative AI]]></category>
		<category><![CDATA[Large Language Models]]></category>
		<category><![CDATA[LLM Architecture]]></category>
		<category><![CDATA[Model Context Protocol]]></category>
		<category><![CDATA[Open Source AI]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15914</guid>

					<description><![CDATA[<p>Have you ever typed something into Claude Code and wondered how it actually works? It’s not too hard to find out, after all, Anthropic accidentally released the Claude Code codebase back in March (The Verge). But what exactly is going on under the hood? How does the architecture function? And how can you build your <a class="read-more" href="https://mobile.fhstp.ac.at/development/ai-agent-harness-claude-code/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/ai-agent-harness-claude-code/">Creating your own custom Agent Harness like Claude Code and why it matters</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">Have you ever typed something into Claude Code and wondered how it actually works? It’s not too hard to find out, after all, Anthropic accidentally released the Claude Code codebase back in March (<a href="https://www.theverge.com/ai-artificial-intelligence/904776/anthropic-claude-source-code-leak">The Verge</a>). But what exactly is going on under the hood? How does the architecture function? And how can you build your own bespoke version of such a system? And do you even want to?</p>



<h2 class="wp-block-heading">What Is an Agent Harness?</h2>



<p class="wp-block-paragraph">Finding a clear-cut definition of an &#8220;agent harness&#8221; isn&#8217;t easy. This is largely because many AI companies are reluctant to give away the exact approach of how their agents work, often disguising the technical definition in marketing jargon that sounds cool or magical (definitions e.g.: <a href="https://cloud.google.com/discover/what-are-ai-agents">Google</a>, <a href="https://developers.openai.com/api/docs/guides/agents/define-agents">OpenAi</a>, <a href="https://www.anthropic.com/engineering/building-effective-agents">Anthropic</a>).</p>



<p class="wp-block-paragraph">The best difinition I could find was one I stumbled over reading a Github repo about &#8220;<a href="https://github.com/RyanAlberts/best-of-Agent-Harnesses">Best of Agent Harnesses and Harness Techniques</a>&#8221; which quoted a Blog entry from <a href="https://simonwillison.net/2025/Sep/18/agents/">Simon Willison’s Weblog</a>: &#8220;An LLM agent runs tools in a loop to achieve a goal.&#8221; (6)</p>



<p class="wp-block-paragraph">Technically speaking, an agent harness is the infrastructure and control layer built around a Large Language Model (LLM). A base model (like Claude 3.7 or GPT-4o) cannot natively search your local files, execute terminal commands, or iteratively fix code—it only generates text. The harness is what grants the LLM autonomy. It provides the model with tools, enforces permissions, manages state, and orchestrates the overarching loop of an agentic session. (1)</p>



<h2 class="wp-block-heading">Inside Claude Code: Architecture Overview</h2>



<p class="wp-block-paragraph">When we examine the architecture of a sophisticated harness like Claude Code, it reveals a highly structured system that goes far beyond a simple chat interface.</p>



<p class="wp-block-paragraph">At its core, the architecture relies on a continuous evaluation loop. The model isn&#8217;t just generating an answer; it&#8217;s navigating a Gather-Act-Verify cycle. (2)</p>



<pre class="wp-block-code"><code>graph TD
    A&#91;User Input / Prompt] --> B(Agent Harness Control Loop)
    B --> C{LLM Decision Engine}
    
    C -- Needs Context --> D&#91;Gather]
    D --> D1(Search Files, Read Memory)
    D1 --> B
    
    C -- Ready to Execute --> E&#91;Act]
    E --> E1(Write Code, Run Terminal)
    E1 --> B
    
    C -- Needs Validation --> F&#91;Verify]
    F --> F1(Run Tests, Check Linting)
    F1 -- Error Found --> B
    F1 -- Success --> G&#91;Final Response to User]</code></pre>



<p class="wp-block-paragraph">Another crucial component of this architecture is Memory Management. Developer Simon Willison highlighted a fascinating architectural detail in a recent blog post comparing the memory implementations of Claude and ChatGPT. (2)<br><br>Claude’s harness philosophy prioritizes extreme transparency. Unlike OpenAI, which often injects user profiles or past context into the background automatically, Claude Code starts every conversation as a blank slate. Memory is implemented as explicit tools (specifically conversation_search and recent_chats).</p>



<pre class="wp-block-code"><code>sequenceDiagram
    participant User
    participant Harness
    participant LLM
    participant MemoryDB
    
    User->>Harness: "Continue where we left off yesterday"
    Harness->>LLM: Pass user prompt
    LLM->>Harness: Tool Call: conversation_search()
    Harness->>MemoryDB: Query past logs
    MemoryDB-->>Harness: Return relevant context
    Harness-->>LLM: Inject context into prompt
    LLM->>User: "Ah yes, we were fixing the routing bug..."</code></pre>



<p class="wp-block-paragraph">Because the model decides when to pull from memory via a visible tool call, you avoid the issue of old &#8220;bug loops&#8221; silently poisoning a fresh workspace.</p>



<h2 class="wp-block-heading">Building Your Own Agent Harness and the benefits</h2>



<p class="wp-block-paragraph">But why should you build your own agent harness when they already exist and work fine? I think its just the same reason why open source software exists. Closed-source systems like Claude Code are incredibly powerful, but they are highly opinionated and tailored to specific workflows (like general software development). By building your own, you gain maximum flexibility.</p>



<p class="wp-block-paragraph">You can customize the exact tools the agent has access to, perhaps integrating it directly with your company&#8217;s proprietary databases, Jira ticketing systems, or internal APIs. Or you can just adjust it for your needs for software developement or general purpose use. Fortunately, you don&#8217;t have to start from scratch. An excellent starting point is the GitHub repository <code>RyanAlberts/best-of-Agent-Harnesses</code>. (4) This curated, weekly-updated list ranks over 100 open-source agent harnesses. Notably, it even includes an MCP (Model Context Protocol) server, <code>llms.txt</code>, and JSON data, allowing agents themselves to read the repository and recommend the best harness framework for your specific needs.</p>



<h2 class="wp-block-heading">For what would i use a &#8220;Harness&#8221; for?</h2>



<p class="wp-block-paragraph">To understand the practical value, let’s look at a real-world project I am doing at work: a system designed to fully automate the production of AI-generated videos.<br>To be honest, the architecture diagram below represents a highly structured pipeline rather than a full-blown autonomous harness, because I have to make it highly predictable. However, it perfectly illustrates the foundational steps. By giving the central &#8220;Orchestrator&#8221; more flexibility and decision-making power, this pipeline could easily evolve into a true agentic harness.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="6194" height="5176" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Diagram-1.png" alt="" class="wp-image-15943" style="aspect-ratio:1.1966900063653725;width:487px;height:auto" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Diagram-1.png 6194w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Diagram-1-1536x1284.png 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Diagram-1-2048x1711.png 2048w" sizes="auto, (max-width: 6194px) 100vw, 6194px" /></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">How would this be agentic then if we give it more freedom to be &#8220;creative&#8221;. If we apply the <strong>Gather-Act-Verify</strong> principles discussed earlier to this exact diagram, the system becomes truly autonomous:</p>



<ul class="wp-block-list">
<li><strong>Gather (Data &amp; Script Prep):</strong> Instead of just following a static script, the agent uses tools to autonomously query the <em>AWS Database</em> for the latest product stats and fetches the correct <em>Presentation Assets</em> (potentially using the Model Context Protocol, MCP, to search through company directories).</li>



<li><strong>Verify (Validation &amp; Creation):</strong> This is where a harness shines. In a rigid pipeline, if the <em>Small compliance/Legal check</em> fails, the system just throws an error and stops. In an agent harness, the LLM catches this error, analyzes <em>why</em> the script failed compliance, and autonomously rewrites it until it passes the check.</li>



<li><strong>Act (Audio, Sync &amp; Rendering):</strong> Once the agent verifies the script is perfect, it triggers the text-to-speech tools, gathers the exact audio timestamps, and hands everything over to the rendering engine before finally publishing it.</li>
</ul>



<h2 class="wp-block-heading">Challenges and Best Practices</h2>



<p class="wp-block-paragraph">If you decide to build a custom harness, keep these best practices in mind:</p>



<ol start="1" class="wp-block-list">
<li><strong>Cost and Latency Control:</strong> Because the agent runs in continuous loops (sending accumulating context back to the model), API costs can skyrocket. Implementing effective <strong>Prompt Caching</strong> is mandatory. (5)</li>



<li><strong>Robust Error Handling:</strong> If a tool (e.g., a terminal command) fails, the harness must not crash. It needs to gracefully catch the error (like a stack trace) and feed it back to the LLM during the <em>Verify</em> phase so the agent can self-correct. (5)</li>



<li><strong>Transparency:</strong> Follow Claude’s example. Don&#8217;t hide memory injections in the system prompt. Implement memory and context retrieval as visible tool calls so users can audit what the agent is doing. (6)</li>



<li><strong>Sandboxing:</strong> Because the <em>Act</em> phase allows the execution of commands, your harness must enforce strict security boundaries (e.g., running actions inside Docker containers) to prevent an autonomous agent from accidentally deleting critical system files. (5)</li>
</ol>



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



<p class="wp-block-paragraph">An agent harness is much more than an API wrapper, it is the vital infrastructure that gives a language model the tools it needs. While leaks and teardowns of commercial tools like Claude Code give us a glimpse into high-end, proprietary architectures, the vast open-source community proves that custom, bespoke solutions are more accessible than ever. By mastering the <em>Gather-Act-Verify</em> loop and maintaining clean, transparent tool management, you can transform a simple text generator into an autonomous, specialized digital colleague. </p>



<p class="wp-block-paragraph">Btw: There is also a very good video if you want to know more about harnesses from Langchain: <a href="https://www.youtube.com/watch?v=HI2q3ci3Iuc&amp;t=409s">https://www.youtube.com/watch?v=HI2q3ci3Iuc&amp;t=409s</a></p>



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



<ol class="wp-block-list">
<li><a href="https://vrungta.substack.com/p/claude-code-architecture-reverse">https://vrungta.substack.com/p/claude-code-architecture-reverse</a></li>



<li><a href="https://michaellivs.com/blog/architecture-behind-claude-code">https://michaellivs.com/blog/architecture-behind-claude-code</a></li>



<li><a href="https://www.mindstudio.ai/blog/claude-code-source-leak-memory-architecture">https://www.mindstudio.ai/blog/claude-code-source-leak-memory-architecture</a></li>



<li><a href="https://github.com/RyanAlberts/best-of-Agent-Harnesses">https://github.com/RyanAlberts/best-of-Agent-Harnesses</a></li>



<li><a href="https://resources.anthropic.com/building-effective-ai-agents">https://resources.anthropic.com/building-effective-ai-agents</a></li>



<li><a href="https://simonwillison.net/2025/Sep/18/agents/">https://simonwillison.net/2025/Sep/18/agents/</a></li>
</ol>
<p>The post <a href="https://mobile.fhstp.ac.at/development/ai-agent-harness-claude-code/">Creating your own custom Agent Harness like Claude Code and why it matters</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/development/ai-agent-harness-claude-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Gymetrics: A Self-Hostable Fitness App with Kotlin Multiplatform, NestJS, and Dockerization</title>
		<link>https://mobile.fhstp.ac.at/allgemein/gymetrics-a-self-hostable-fitness-app/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/gymetrics-a-self-hostable-fitness-app/#respond</comments>
		
		<dc:creator><![CDATA[Jakob Laschober]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 06:49:00 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[AI Coding Agents]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Compose Multiplatform]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Fitness App]]></category>
		<category><![CDATA[KMP]]></category>
		<category><![CDATA[Koin Dependency Injection]]></category>
		<category><![CDATA[Kotlin Multiplatform]]></category>
		<category><![CDATA[MCP Server]]></category>
		<category><![CDATA[Mobile Architecture]]></category>
		<category><![CDATA[Model Context Protocol]]></category>
		<category><![CDATA[NestJs]]></category>
		<category><![CDATA[offline-first]]></category>
		<category><![CDATA[Self-Hosted App]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15928</guid>

					<description><![CDATA[<p>I set out to build this app in my first semester as a simple replacement for the Excel spreadsheet I used for workout tracking. But in the process of making it, it became so much more. And if you want to check it out you can on gymetrics.at (yeah I&#8217;ve already bought a Domain &#8230;). <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/gymetrics-a-self-hostable-fitness-app/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/gymetrics-a-self-hostable-fitness-app/">Gymetrics: A Self-Hostable Fitness App with Kotlin Multiplatform, NestJS, and Dockerization</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">I set out to build this app in my first semester as a simple replacement for the Excel spreadsheet I used for workout tracking. But in the process of making it, it became so much more. And if you want to check it out you can on <a href="https://gymetrics.at/">gymetrics.at</a> (yeah I&#8217;ve already bought a Domain &#8230;).</p>



<p class="wp-block-paragraph">When I started out, I decided to make an application that was really worth trying. I designed a database structure and a system architecture that I meant to be perfect. But for my first frontend (tbh not only the frontend), I was struggling. I am no designer myself and couldn&#8217;t really create a smooth user flow, so I used AI to help me with that. After I was done, I wasn&#8217;t very happy with either the scalability or the look and feel. I had used Ionic, a web framework that ran in a WebView on the device. The touch inputs didn&#8217;t feel instant or responsive enough, and for what was basically a simple CRUD app, it felt a little bit sluggish (or maybe that’s just me).</p>



<p class="wp-block-paragraph">So, in my second semester, I focused on refining that whole experience and making it better in every way.</p>



<h3 class="wp-block-heading">The Rewrite: Embracing Kotlin Multiplatform</h3>



<p class="wp-block-paragraph">I decided on a new frontend framework: Kotlin Multiplatform (KMP), which allows you to build apps for nearly any platform using a shared codebase. I also added new features, like self-hosted AI solutions to generate content and a posibility to choose your  current Gym.</p>



<p class="wp-block-paragraph">Implementing my app with Kotlin was challenging because it was a completely new programming language to me. After learning the fundamentals and coding on my own for the first week, I brought in some AI coding agents to help speed up the process. At first, I used a local model called <code>qwen3-coder:30b</code>, which I quantized to run on constrained hardware. My setup was a Mac Book Air M1 from the USTP rental service running <a href="https://omlx.ai/" data-type="link" data-id="https://omlx.ai/">OMLX</a> (which was especially built for Macs to take advantage of their unified memory). Running in my IDE was the open-source AI code agent <a href="https://marketplace.visualstudio.com/items?itemName=Continue.continue">Continue</a>, which allowed me to implement MCP servers and feed code context from my project to the model. Later I learned that this extention or IDE whatever you wanna call it, is no longer being developed and was acquired by Cursor.</p>



<p class="wp-block-paragraph">After I sadly had to return the rental Mac (originally i wanted to use it for building the App for IOS as well but just failed to finish the App in time <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f641.png" alt="🙁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ) , I switched to Claude Code. For me, it was essential to double-check Claude’s work and architectural decisions. Honestly, I was a little bit shocked by some of the choices it made, like trying to store API keys or passwords in plain text just somewhere in the Code! To be fair, I wasn&#8217;t using their frontier model to avoid spending too many tokens (as I argued a lot with it during the development process), but still. However, it was particularly handy for creating the frontend layer with Jetpack Compose, thanks to the vast documentation available for Android&#8217;s UI framework.</p>



<p class="wp-block-paragraph">To avoid hallucinations and provide the model with up-to-date documentation, I added an MCP Server called <a href="https://context7.com/">Context7</a>. It allowed me to filter exactly what documentation the model received and what it had access to &#8230; a really handy tool.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="960" height="2142" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot_20260916-220509.png" alt="" class="wp-image-16013" style="aspect-ratio:0.4481865284974093;width:289px;height:auto" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot_20260916-220509.png 960w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot_20260916-220509-688x1536.png 688w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot_20260916-220509-918x2048.png 918w" sizes="auto, (max-width: 960px) 100vw, 960px" /></figure>



<h3 class="wp-block-heading">Frontend Challenges: Caching, Offline Sync, and Navigation</h3>



<p class="wp-block-paragraph"><br>The hardest part of my frontend implementation was the caching logic. I wanted the app to always instantly display the relevant information you need in the moment. To achieve this, I decided to cache the first 10 items of every category (e.g., Templates, Trainings, UserData).</p>



<p class="wp-block-paragraph">All of this is stored in a Key-Value database called <a href="https://github.com/xxfast/KStore">KStore</a>, a small library that works great for simple data storage on Android and iOS devices. The absolute hardest part was defining the behavior for when I saved something offline, ensuring that the moment I got back online, it would post to the backend so the two storages would &#8220;sync&#8221; up again. We now have a (mostly) robust network-first cache strategy with offline fallbacks.</p>



<p class="wp-block-paragraph">I also completely revamped the app&#8217;s navigation and UI architecture using Compose Multiplatform: </p>



<ul class="wp-block-list">
<li><strong>Two-Level Navigation:</strong> We have an outer navigation graph for the Auth-Flow (Login/Register) and an inner graph wrapped in a <code>Scaffold</code> for the main tabs. This allows for a persistent BottomBar that stays visible while you switch tabs.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Profile Dialog:</strong> Instead of routing to a new screen, the user profile opens as a clean Dialog Card over the current screen, making it feel much faster.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Security:</strong> Tokens are stored securely using <code>KVault</code> (Keychain for iOS, EncryptedSharedPreferences for Android).</li>
</ul>



<ul class="wp-block-list">
<li><strong>Dependency Injection:</strong> I used Koin to keep the architecture clean (MVVM), allowing the UI to remain logic-free.</li>
</ul>



<h3 class="wp-block-heading">The Backend: Keeping it Clean &amp; Adding a Scraping Service</h3>



<p class="wp-block-paragraph">For my backend (a self-hosted NestJS API), I tried to make major improvements to security and code cleanliness. Most of my backend wasn&#8217;t even touched by AI &#8230; I mean aside from a few MongoDB queries &#8230; they&#8217;re just really weird to write ok? &#8230; so I could assure everything was up to my expectations.</p>



<p class="wp-block-paragraph">For extended features, I added a custom scraping service using a separate Python server. It scrapes all the fitness studios listed on my gym&#8217;s website and writes everything about their equipment directly into my database. It&#8217;s scheduled to run on startup and then one time per Month (don&#8217;t want to get accused of creating to much net traffic for them). I deployed this service in a separate Docker container within the same Docker network to ensure minimal downtime in case the scraper ever crashes.</p>



<h3 class="wp-block-heading">Building a Local AI Agent for Training Templates</h3>



<p class="wp-block-paragraph">Having the exact context of my gym&#8217;s equipment in the database was especially helpful for my next big feature: Local AI Training Template generation.</p>



<p class="wp-block-paragraph">To be honest, I initially wanted to use the MCP server I had programmed earlier for this task. But by the time I got to implementing the AI feature, I realized that Ollama doesn&#8217;t actually support MCP natively because it lacks an MCP client.</p>



<p class="wp-block-paragraph">So, I built an Agentic loop directly in my NestJS backend to act as a middleman between Ollama and my server. I <em>could</em> have gone the route of calling my MCP server through my backend and called it a day. But after a short &#8220;question battle&#8221; with Claude Code, I decided that wasn&#8217;t feasible due to the unnecessary network requests I could save by just implementing the agent loop directly in the backend.</p>



<p class="wp-block-paragraph">My custom MCP Server now exists on its own and isn&#8217;t connected to anything just yet. But building it was a fantastic learning experience regarding how these systems work. It lays the groundwork for future implementations, as I eventually plan to integrate external MCP-capable AI tools like Claude or ChatGPT.</p>



<h3 class="wp-block-heading">Technical Deep Dive: Gymetrics Feature List</h3>



<p class="wp-block-paragraph">For those interested in the exact tech stack and architectural decisions, here is a breakdown of what’s running under the hood:</p>



<p class="wp-block-paragraph"><strong>The Stack</strong></p>



<ul class="wp-block-list">
<li><strong>Frontend:</strong> Kotlin Multiplatform, Compose Multiplatform (Shared UI), targeting Android (first priority) and iOS.</li>



<li><strong>Backend:</strong> Self-hosted NestJS API with Dockerized microservices.</li>



<li><strong>Auth:</strong> Short-lived Bearer tokens + Refresh tokens.</li>
</ul>



<p class="wp-block-paragraph"><strong>Core Implementations</strong></p>



<ul class="wp-block-list">
<li><strong>Ktor Client &amp; Auto-Refresh:</strong> Centralized HTTP client handling JSON serialization, timeouts, and dynamic base URLs. Used the Ktor <code>Auth</code> plugin to automatically attach tokens and trigger a silent refresh route (<code>POST /auth/refresh</code>) on 401 errors.</li>



<li><strong>Offline-First Capabilities:</strong> Built a custom <code>ConnectivityObserver</code> that tracks network state app-wide. The app displays an offline badge in the TopBar and handles offline Auth checks by optimistically trusting the securely stored token.</li>



<li><strong>App-Wide Theming:</strong> Implemented a custom <code>GymetricsTheme</code> wrapper around MaterialTheme, featuring a sleek, app-wide dark mode and adaptive Android icons.</li>



<li><strong>State Management &amp; DI:</strong> Strict MVVM architecture. State is handled via <code>sealed interfaces</code> and exhaustive <code>when</code> statements (Idle/Loading/Success/Error). Dependency Injection is handled entirely by <strong>Koin</strong> (using <code>appModule</code>, <code>single</code>, and <code>viewModelOf</code>).</li>
</ul>



<p class="wp-block-paragraph">It’s been a massive journey from a simple Ionic prototype to a fully-fledged, offline-capable KMP application with agentic AI workflows. It started as a way to replace a spreadsheet, but it taught me modern mobile architecture, backend, and how to effectively wrangle AI coding assistants.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/gymetrics-a-self-hostable-fitness-app/">Gymetrics: A Self-Hostable Fitness App with Kotlin Multiplatform, NestJS, and Dockerization</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/gymetrics-a-self-hostable-fitness-app/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Seed Data Is Not Test Data: Building a Realistic Development Database</title>
		<link>https://mobile.fhstp.ac.at/allgemein/seed-data-is-not-test-data-building-a-realistic-development-database/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/seed-data-is-not-test-data-building-a-realistic-development-database/#respond</comments>
		
		<dc:creator><![CDATA[Csongor]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 23:24:16 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=16009</guid>

					<description><![CDATA[<p>This blog article argues whether database seeding should make the application look as if ordinary users have already been using it, in contrast to showcasing edge cases and test suits. While seed scripts in reality can be used to accomplish both the argument is not that seed data can never support testing but instead that one development dataset should not be filled with every technical edge case.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/seed-data-is-not-test-data-building-a-realistic-development-database/">Seed Data Is Not Test Data: Building a Realistic Development Database</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">This blog article argues whether database seeding should make the application look as if ordinary users have already been using it, in contrast to showcasing edge cases and test suits. While seed scripts in reality can be used to accomplish both the argument is not that seed data can never support testing but instead that one development dataset should not be filled with every technical edge case.</p>



<h2 class="wp-block-heading">1. Introduction</h2>



<p class="wp-block-paragraph">When developing an application the developer doesn&#8217;t want to repeat the process or creating a user, then listing a product, sending messages, and so on just to be able to test a new feature they are working on. Manually creating records in the database wastes time especially if it has to be done frequently. A seed script solves this issue so the developer doesn&#8217;t have to start from zero every time. How ever seeds can also hinder development if it gets bloated with testing every single scenario possible with potential technical non-realistic naming, missing fields and placeholders. <strong>What should a useful development seed actually contain?</strong></p>



<h2 class="wp-block-heading">2. <strong>Seed data and test data serve different purposes</strong></h2>



<p class="wp-block-paragraph">First of all, database seeding means to populate a database with initial records after its structure has been created (<a href="https://supabase.com/docs/guides/local-development/seeding-your-database">Supabase</a>). Seeds may include reference data like roles, categories, or settings. It provides a constant and reproduceable sample dataset for development. I can also provide a prepared environment to conduct specific tests. This blog post differentiates two main use cases for seed data.</p>



<p class="wp-block-paragraph"><strong>Development Demo Data</strong><br>First development demo data&#8217;s aim is to produce a regular environment for manual use of the application. It makes the application understandable and useable out of the box. These are really only used in local development to hep with developing or demonstrating features.</p>



<p class="wp-block-paragraph"><strong>Test Fixtures</strong><br>These are created for specific scenarios that are aimed at smaller parts of the application. The seed data contains only the required states for the given test. This isolates areas of the application and uses less time and processing power because its meant to be dropped often (<a href="https://playwright.dev/docs/test-fixtures">playwright</a>).</p>



<h2 class="wp-block-heading"><strong>3. <strong>Properties of useful development seed data</strong></strong></h2>



<p class="wp-block-paragraph"><strong>How unrealistic seed data hurts development</strong><br>The realism behind the data that is seeded into the database has high significance when finalizing or demonstrating features. Technical labels and placeholders can make or break the UI. A poor seed can create presentation problems, development, and usability problems. To try and avoid these watch out for the following properties.</p>



<p class="wp-block-paragraph"><strong>a. Believable visible content</strong><br>Names, titles and descriptions are all textual information that need to look natural and follow the application. Other data such as prices with currencies and dates should be reasonable. Images also play a major role and are not an easy thing to make realistic. Finally one of the most important factor is not to use user-facing fields for storing developer notes or technical naming.</p>



<p class="wp-block-paragraph"><strong>b. Relationships</strong><br>Filling out the table row by row is not best practice to make the data look realistic. A solution for this is to create a few users and create connected records around a few scenarios demonstrating complete workflows.</p>



<p class="wp-block-paragraph"><strong>c. Representativeness</strong><br>Make sure that all major features of the application are represented in the seed data. This doesn&#8217;t have to cover every single possibility, but allow the developer to see functioning features.</p>



<p class="wp-block-paragraph"><strong>d. Safe information</strong><br>One might ask why not just use production data if available? There are many cases where that is the solution to diagnose a bug for build a highly specific feature. The issue is the handling of personal information. Ideally when using production data a different script should be used to anonymize the data. Even if that is the case real data has to be used with extra care and may add difficulty and require more time when developing, hence the safest option is to use invented but realistic looking data.</p>



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



<p class="wp-block-paragraph">I decided to choose this topic because i encountered database seeding in multiple development environments before and I have always thought that I would do it a bit differently. Then I started my own project that had seeding for the first time fully controlled by myself. I experienced both ends of the scale either putting too many scenarios and potential edge cases in the seed data or lacking the ability to instantly test some feature. Finally I believe multiple seeding scripts are ideal and a middle point has to be found between maintenance requirement and usefulness due to the size some seeds can grow to.</p>



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



<p class="wp-block-paragraph"><a href="https://www.prisma.io/docs/orm/v7/prisma-migrate/workflows/seeding">https://www.prisma.io/docs/orm/v7/prisma-migrate/workflows/seeding</a></p>



<p class="wp-block-paragraph"><a href="https://supabase.com/docs/guides/local-development/seeding-your-database">https://supabase.com/docs/guides/local-development/seeding-your-database</a></p>



<p class="wp-block-paragraph"><a href="https://playwright.dev/docs/test-fixtures">https://playwright.dev/docs/test-fixtures</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/seed-data-is-not-test-data-building-a-realistic-development-database/">Seed Data Is Not Test Data: Building a Realistic Development Database</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/seed-data-is-not-test-data-building-a-realistic-development-database/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RevMatchMarket Phase 2 – From Swipe-Based Browsing to Buyer-Seller Communication</title>
		<link>https://mobile.fhstp.ac.at/allgemein/revmatchmarket-phase-2-from-swipe-based-browsing-to-buyer-seller-communication/</link>
					<comments>https://mobile.fhstp.ac.at/allgemein/revmatchmarket-phase-2-from-swipe-based-browsing-to-buyer-seller-communication/#respond</comments>
		
		<dc:creator><![CDATA[Csongor]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 21:40:10 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Web-App]]></category>
		<guid isPermaLink="false">https://mobile.fhstp.ac.at/?p=15917</guid>

					<description><![CDATA[<p>1. Introduction Rev Match Market is a used car marketplace lead by the left right swiping mechanism for marking interest in used car postings and connecting buyers with sellers. This blog post describes the second phase of development that took place on this project. Initially a MVP was made in the 1st phase that already <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/revmatchmarket-phase-2-from-swipe-based-browsing-to-buyer-seller-communication/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/revmatchmarket-phase-2-from-swipe-based-browsing-to-buyer-seller-communication/">RevMatchMarket Phase 2 – From Swipe-Based Browsing to Buyer-Seller Communication</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">1. Introduction</h2>



<p class="wp-block-paragraph">Rev Match Market is a used car marketplace lead by the left right swiping mechanism for marking interest in used car postings and connecting buyers with sellers. This blog post describes the second phase of development that took place on this project. Initially a MVP was made in the 1st phase that already contained the following features: authenticated sessions, swipe-based discovery, favorites, and seller listing management. For further reading about the 1st phase find the previous blog post <a href="https://mobile.fhstp.ac.at/allgemein/rev-match-market-a-swipe-based-used-car-marketplace/">here</a>.</p>



<p class="wp-block-paragraph">As a continuation to the initial MVP, the 2nd phase&#8217;s main goal was to introduce buyer-seller communication within the application aided with a notification system informing buyers and sellers about new interactions from each other. Another goal was to significantly improve the mobile experience and expand the capability of the UI from a single mobile view to a responsively transitioning UI that supports desktop, tablet, and mobile. Additional goals were the implementation of a concrete sold state that could later be the starting point of KPI tracking. Finally, to be able to later experiment with the app as a real business the application structure and code quality was to be made more production-ready.</p>



<h2 class="wp-block-heading">2. From Phase 1 MVP to Phase 2 &#8211; The Plan</h2>



<p class="wp-block-paragraph">The starting point of the 2nd phase was directly from where phase 1 and the last blog post left off.</p>



<ul class="wp-block-list">
<li>Authenticated marketplace.</li>



<li>Seller listing creation, editing and soft deletion.</li>



<li>Swipe-based discovery with LIKE and PASS.</li>



<li>Favorites and basic make/model/price filtering.</li>



<li>Nuxt, NestJS, PostgreSQL and Prisma foundation.</li>
</ul>



<p class="wp-block-paragraph">The features implemented by phase 2 in order of priority.</p>



<ul class="wp-block-list">
<li>Mobile-first redesign before implementing major new screens.</li>



<li>Chat and in-app notifications as the main new product features.</li>



<li>Improved marketplace filtering and incremental feed loading.</li>



<li>Cleaner domain boundaries, response contracts and privacy handling.</li>
</ul>



<p class="wp-block-paragraph">The result speak for them self, even if at this point of the blog only visually.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large size-full"><img loading="lazy" decoding="async" width="1699" height="944" data-id="16003" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-131945-3.png" alt="" class="wp-image-16003" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-131945-3.png 1699w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-131945-3-1536x853.png 1536w" sizes="auto, (max-width: 1699px) 100vw, 1699px" /></figure>
</figure>



<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" style="flex-basis:100%"></div>
</div>



<h2 class="wp-block-heading">3. The Mobile-First Interface</h2>



<p class="wp-block-paragraph"><strong>Shared Application Shell</strong><br>The shell places the screens in a wrapping element which provides consistent navigation throughout the navigation between pages and also provides a responsive layout. The components and visual primitives used in the application are also standardized across the different pages including spacing, typography and interaction states. This meant that many components from phase 1 have been completely replaced with special care so no parallel or redundant designs would have to be maintained.</p>



<p class="wp-block-paragraph"><strong>Screen Changes and Account Identity</strong><br>To start off at the beginning of users journey the login and registration pages have been completely redesigned and made responsive, along with the swipe, car-detail, favorites and seller-listing screens. A visible addition to the users was also made by displaying a name for user facing identity. The user identity also gained increased protection, since emails and user IDs of other users are no longer reaching the frontend other than public contact information on car-detail pages. </p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="545" height="1189" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/Screenshot-2026-09-16-132131.png" alt="" class="wp-image-15934" style="aspect-ratio:0.45837641540362645;width:192px;height:auto"/><figcaption class="wp-element-caption">Swipe page of the application with demo data where users brows listings.</figcaption></figure>



<h2 class="wp-block-heading"><strong>4. Improving Marketplace Discovery</strong></h2>



<p class="wp-block-paragraph">A task originally coming from phase 1 has been implemented and improved, which is pagination and filtering of the queue of cars on the swipe page. First of all Filtering did already exist but it is now moved from the frontend to the backend. The number of filters remains small though now its way easier to expand. The front end now only holds a limited number of cars that come next and before the queue is exhausted the prefetching of new cars occurs. Pass decisions still expire and listings return to the queue later.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="3760" height="3160" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-1.png" alt="" class="wp-image-16005" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-1.png 3760w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-1-1536x1291.png 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-1-2048x1721.png 2048w" sizes="auto, (max-width: 3760px) 100vw, 3760px" /></figure>



<h2 class="wp-block-heading">5. Communication (Chat), Notifications and Sale Lifecycle</h2>



<p class="wp-block-paragraph">This section is arguably the most important for phase 2. This encapsulates Likes creating conversations, the chat experience between buyer and seller, in-app notifications, and a new state for listings &#8220;SOLD&#8221;.</p>



<p class="wp-block-paragraph"><strong>LIKEs and conversations</strong><br>As one can know from phase 1 when a user likes a listing, the listing appears in the users favorites tab. Now following that the seller also receives a notification of a potential buyer who liked their listing. To avoid the creation of empty conversations a like in it self doesn&#8217;t create a new conversation. Following the like both parties get the chance to initiate a conversation. The seller can initiate from the notification they receive and the buyer can start a chat from the favorites tab or the car-detail page. Either way a new conversation is created when the first message is sent. There can only be one conversation per car and interested buyer.</p>



<p class="wp-block-paragraph"><strong>Chat experience</strong><br>Chats appear in a list like page which provides basic information to the user about all the chats like total number of unread messages and about individual list items representing a single chat like the last message, the time it was sent and the car that is the subject of the conversation. Chats can still be reached following a successful sale or if a buyer decided to withdraw interest. When a listing is deleted the chat is still readable but new messages are blocked.</p>



<p class="wp-block-paragraph"><strong>In-app Notifications</strong><br>The two sources of notifications are the Likes and messages. When the application is open and the user receives a notification an in-app popup appears temporarily. In case the user misses the popup, they might still access the notifications in their inbox with a list view. The notification inbox list view similarly to the chat shows notification contents, read or unread states and a counter for all unread notifications. The user can mark only one notification or all at the same time as read.</p>



<p class="wp-block-paragraph"><strong>Sold Listing</strong><br>The listings can be marked as sold only by the seller. They can do this either from the listing itself or the conversation which will associate the conversation with the successful sale. Sold listings can’t be found on the swipe page anymore and buyers may no longer start new conversations about the sold listings. Within favorites or existing conversations, the listing shows up as sold.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="3760" height="3560" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image.png" alt="" class="wp-image-16004" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image.png 3760w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-1536x1454.png 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-2048x1939.png 2048w" sizes="auto, (max-width: 3760px) 100vw, 3760px" /></figure>



<h2 class="wp-block-heading"><strong>6. Technical Foundation and Data Model</strong></h2>



<ul class="wp-block-list">
<li>RevMatchMarket still uses Nuxt 4 for the frontend, NestJS for the backend, and PostgreSQL with Prisma ORM for the database.</li>



<li>New persistence models that were added in phase 2 are conversations, messages, notifications, and sold state.</li>



<li>A major change is the increased privacy meaning that response DTOs no longer expose account email and userID.</li>



<li>The development process was also improved between phases 1 and 2 by using dedicated git feature branches merged into develop and later charry picking from develop to main (production).</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="10460" height="3960" src="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-3.png" alt="" class="wp-image-16007" srcset="https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-3.png 10460w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-3-1536x582.png 1536w, https://mobile.fhstp.ac.at/wp-content/uploads/2026/09/image-3-2048x775.png 2048w" sizes="auto, (max-width: 10460px) 100vw, 10460px" /></figure>



<h2 class="wp-block-heading"><strong>7. Challenges and Lessons Learned</strong></h2>



<p class="wp-block-paragraph">The first challenge was to plan the chat and notification system before implementation, what I learned is that it is significantly easier if the process is visualized beforehand using one of many flow chat methods. I also learned about the effort required to produce production grade code, where edge cases have to be treated with special care. I have learnt about several new techniques listed below.</p>



<p class="wp-block-paragraph"><strong>Cursor Pagination</strong><br>Pagination is used when requesting batches of a long list of data from the API. Cursor pagination loads the next group of records relative to the last record already received. This differs from the more simple offset pagination which requests by skipping x amount of records from the start. A cursor marks the last record loaded by a deterministic value in most cases a timestamp and the record&#8217;s id. This is used on RevMatchMarket&#8217;s swipe feed, and notification and chat inbox for example to avoid duplicate or skipped records.</p>



<p class="wp-block-paragraph"><strong>Client-side Reconciliation</strong><br>Reconciliation is to be understood as checking back with the API new data based on the data the browser already had. This process merges new server data with the existing state of the browser. This technique is important mainly because the application uses polling to fetch new messages or notifications. In case a notification is deleted and at the same time the polling occurs the deleted notification may appear again because the polling happened before the delete went through. When new server data arrives it is merged with the browser data by comparing IDs and the newer updatedAt wins over the older one.</p>



<p class="wp-block-paragraph"><strong>Prefetching</strong><br>The swipe page uses prefetching to achieve a continues feed. When only 3 cars remain from the previous batch of 20 a newer batch is fetched. To have a fluid swipe feed additional steps are also taken to filter out duplicates, potentially successful swipes can&#8217;t be re-introduced again, and account and filter changes are watched.</p>



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



<p class="wp-block-paragraph">The development in the 2nd phase yielded the following results: a completely reworked design and application structure, the ability for buyers and sellers to connect within the application after a potential buyer liked a listing, a notification system to keep buyers and sellers up to date with liked and owned listings, and finally a revised discovery logic that is more reliable and scalable.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/revmatchmarket-phase-2-from-swipe-based-browsing-to-buyer-seller-communication/">RevMatchMarket Phase 2 – From Swipe-Based Browsing to Buyer-Seller Communication</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/revmatchmarket-phase-2-from-swipe-based-browsing-to-buyer-seller-communication/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
