<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
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/">
	<channel>
		<title>Engineering Resources | Infinum</title>
		<atom:link href="https://infinum.com/blog/category/engineering/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/category/engineering/</link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 03 Apr 2026 12:58:20 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>19274777https://infinum.com/uploads/2026/01/moltbot-hero-visual.webp</url>
				</image>
				<title>OpenClaw: Viral AI Sidekick That Puts You and Your Data at Risk</title>
				<link>https://infinum.com/blog/openclaw-moltbot-clawdbot-viral-ai-sidekick/</link>
				<pubDate>Fri, 30 Jan 2026 15:53:11 +0000</pubDate>
				<dc:creator>Hrvoje Filaković</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19274777</guid>
				<description>
					<![CDATA[<p>OpenClaw showcases how powerful “local-first” AI agents can be, but it also shows how quickly convenience can turn into a security liability.</p>
<p>The post <a href="https://infinum.com/blog/openclaw-moltbot-clawdbot-viral-ai-sidekick/">OpenClaw: Viral AI Sidekick That Puts You and Your Data at Risk</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-246"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-93">
	<p	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-94'
	>
	If you haven’t kept up with AI tooling discussions, you may have missed OpenClaw (formerly Moltbot and Clawdbot). Marketed as &#8220;The AI that actually does thing<em>s,</em>&#8221; it acts as your personal AI assistant that can clear your inbox, send emails, manage your calendar, and even check you in for flights. It also acts out – to say the least.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-96"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-97">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/02/Screenshot-2026-02-02-at-11.45.50.webp"
					class="image__img block-media__image-img"
					alt=""
										height="494"
															width="733"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-100'
	>
	What sets Moltbot apart from cloud-only assistants is its deep integration with applications already running on your system, such as WhatsApp, Telegram, Slack, and Discord. It interacts directly with your operating system to manage everyday tasks, bringing AI assistance into your local workflow rather than keeping it locked behind a web interface.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-103'
	>
	However, from a security standpoint, this level of access is bordering on a worst-case scenario. This is the same principle we found in our experiment on <a href="https://infinum.com/blog/ai-generated-code-security-risks/">AI-generated code security risks</a> — AI systems don&#8217;t fail because they lack capability, they fail because they make incorrect assumptions about trust.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-106"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-highlighted-text">
	<p	class='typography typography--size-30-text js-typography block-highlighted-text__typography'
	data-id='es-105'
	>
	<strong> If it can operate on your system, it can compromise it.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-section-intro" data-id="es-107">
	<div
	class="section-intro block-section-intro__section-intro section-intro__divider--down section-intro--no-paragraph"
	data-id="es-108"
	 data-type='default'>
	
	
			<div class="section-intro__inner">
			<h2	class='typography typography--size-36-text js-typography section-intro__title'
	data-id='es-109'
	>
	Inherently Risky by Design</h2>
			<div class="section-intro__wrap">
				<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__icon-position--right section-intro__button js-block-section-intro-button"
	data-id="es-110"
	>
		<div class="btn__inner">
							
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-112'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>			</div>
		</div>
	
			<hr class="section-intro__divider" aria-hidden="true" />
	</div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-115'
	>
	The developers are transparent about the dangers. Moltbot&#8217;s installer explicitly outlines its extensive capabilities and describes the system as &#8220;<em>inherently risky</em>&#8220;. While this transparency is commendable, it highlights the unusually broad level of access the AI operates with.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-117"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-118">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="611"
															width="1195"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-122"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-120">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-121'
	>
	During onboarding, the system prompts you to enable &#8220;<em>skills,</em>&#8221; which are essentially permission scopes granting the bot access to local applications and external services. Some of these are highly sensitive:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-125"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-123">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-124'
	>
	<li>1Password: granting access to a vault means the AI can be entrusted with the keys to nearly every account a user owns.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-128"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-126">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-127'
	>
	<li>Personal data: skills for Apple Notes, Reminders, and Bear-notes give the bot a very high degree of privacy access.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-131"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-129">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-130'
	>
	<li>System commands: agents can run commands and read or write files on your machine.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-134"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-132"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-133">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="554"
															width="1133"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-141"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-section-intro" data-id="es-135">
	<div
	class="section-intro block-section-intro__section-intro section-intro__divider--down section-intro--no-paragraph"
	data-id="es-136"
	 data-type='default'>
	
	
			<div class="section-intro__inner">
			<h2	class='typography typography--size-36-text js-typography section-intro__title'
	data-id='es-137'
	>
	The Unauthenticated Dashboard: Global Exposure</h2>
			<div class="section-intro__wrap">
				<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__icon-position--right section-intro__button js-block-section-intro-button"
	data-id="es-138"
	>
		<div class="btn__inner">
							
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-140'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>			</div>
		</div>
	
			<hr class="section-intro__divider" aria-hidden="true" />
	</div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-144"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-142">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-143'
	>
	After installation, Moltbot exposes a local web dashboard running on <strong>port 18789</strong> by default. This serves as the primary control panel for managing the bot&#8217;s capabilities.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-145"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-146">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="696"
															width="1106"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-148">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-149'
	>
	The critical issue is that there is <strong>no authentication mechanism</strong> in place. If this dashboard is exposed to the internet, any unauthenticated user can interact with the underlying operating system and connected services.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-151">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-152'
	>
	This is not a hypothetical risk. A simple Censys query reveals more than <strong>1,500 publicly exposed, unauthenticated Clawdbot instances</strong>. These real-world deployments grant unrestricted access to anyone who stumbles across them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-156"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-154"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-155">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image5.webp"
					class="image__img block-media__image-img"
					alt=""
										height="538"
															width="1223"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-163"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-section-intro" data-id="es-157">
	<div
	class="section-intro block-section-intro__section-intro section-intro__divider--down section-intro--no-paragraph"
	data-id="es-158"
	 data-type='default'>
	
	
			<div class="section-intro__inner">
			<h2	class='typography typography--size-36-text js-typography section-intro__title'
	data-id='es-159'
	>
	System Interaction and Leaking API Keys</h2>
			<div class="section-intro__wrap">
				<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__icon-position--right section-intro__button js-block-section-intro-button"
	data-id="es-160"
	>
		<div class="btn__inner">
							
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-162'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>			</div>
		</div>
	
			<hr class="section-intro__divider" aria-hidden="true" />
	</div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-164">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-165'
	>
	As for the chatbot itself, it delivers exactly what is promised: it can reliably execute system commands.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-169"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-167"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-168">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image6.webp"
					class="image__img block-media__image-img"
					alt=""
										height="439"
															width="889"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-170">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-171'
	>
	The bot does have some built-in safety measures; by default, it will refuse to execute suspicious commands like reading the <strong>.env</strong> file that contains API keys.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-173"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-174">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image7.webp"
					class="image__img block-media__image-img"
					alt=""
										height="202"
															width="1018"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-176">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-177'
	>
	However, these guardrails are easily bypassed. While prompt injection is a known threat, the simplest way to extract this sensitive data is to ask the bot to list <strong>environment variables</strong>. This can immediately leak the <strong>OPENAI_API_KEY</strong> and other critical credentials that are used and configured.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-181"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-179"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-180">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image8.webp"
					class="image__img block-media__image-img"
					alt=""
										height="462"
															width="993"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-188"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-section-intro" data-id="es-182">
	<div
	class="section-intro block-section-intro__section-intro section-intro__divider--down section-intro--no-paragraph"
	data-id="es-183"
	 data-type='default'>
	
	
			<div class="section-intro__inner">
			<h2	class='typography typography--size-36-text js-typography section-intro__title'
	data-id='es-184'
	>
	Malicious Actors on the Hype Train</h2>
			<div class="section-intro__wrap">
				<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__icon-position--right section-intro__button js-block-section-intro-button"
	data-id="es-185"
	>
		<div class="btn__inner">
							
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-187'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>			</div>
		</div>
	
			<hr class="section-intro__divider" aria-hidden="true" />
	</div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-191"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-189">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-190'
	>
	The viral popularity of the tool has also attracted bad actors. One reported case involved a <strong>fake Visual Studio Code extension</strong> posing as a &#8220;<em>ClawdBot Agent</em>&#8220;. While it looked like a legitimate installer, it was actually secretly installing credential stealer on user&#8217;s systems.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-194"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-192"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-193">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2026/01/image9.webp"
					class="image__img block-media__image-img"
					alt=""
										height="870"
															width="1248"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-197"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-195">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-196'
	>
	<em>Source: </em><a href="https://www.aikido.dev/blog/fake-clawdbot-vscode-extension-malware"><em>https://www.aikido.dev/blog/fake-clawdbot-vscode-extension-malware</em></a></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-204"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-section-intro" data-id="es-198">
	<div
	class="section-intro block-section-intro__section-intro section-intro__divider--down section-intro--no-paragraph"
	data-id="es-199"
	 data-type='default'>
	
	
			<div class="section-intro__inner">
			<h2	class='typography typography--size-36-text js-typography section-intro__title'
	data-id='es-200'
	>
	Our Security Recommendations</h2>
			<div class="section-intro__wrap">
				<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__icon-position--right section-intro__button js-block-section-intro-button"
	data-id="es-201"
	>
		<div class="btn__inner">
							
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-203'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>			</div>
		</div>
	
			<hr class="section-intro__divider" aria-hidden="true" />
	</div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-207"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-205">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-206'
	>
	Specific Tips Moltbot/Clawdbot Users:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-210"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-208">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-209'
	>
	<li><strong>Bind to localhost:</strong> ensure that the dashboard is <strong>only</strong> accessible to localhost (127.0.0.1). Never expose port 18789 to the public internet. Additionally, Moltbot can also be used from the terminal directly without a dashboard.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-213"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-211">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-212'
	>
	<li>Set appropriate allowlists: explicitly define which applications, commands, file paths, and integrations (APIs) Moltbot is allowed to access, and deny everything else by default.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-216"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-214">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-215'
	>
	<li><strong>Treat the bot as a tool:</strong> do not leave it running unattended with broad permissions, especially on shared systems, and lock down access as you would for any automation at this level.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-219"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-217">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-218'
	>
	While AI agents are highly effective for automation, they also introduce significant risks — especially when built without proper security design from the start. If you&#8217;re building agents for your business rather than experimenting with third-party tools, see how we approach <strong><a href="https://infinum.com/artificial-intelligence/agent-development/">AI agent development</a></strong> with security and governance built in. To keep your data and devices safe in the meantime, follow these best practices:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-222"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-220">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-221'
	>
	<li><strong>Isolate installations:</strong> always deploy experimental AI agents in <strong>virtualized or sandboxed environments</strong> to minimize impact on your main system.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-225"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-223">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-224'
	>
	<li><strong>Use dummy accounts:</strong> never provide your primary personal or work credentials to unknown services. Use <strong>test API keys</strong> that can be revoked immediately.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-228"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-226">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-227'
	>
	<li><strong>Verify sources:</strong> only install software from trusted and official sources to avoid hype-driven malware.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-231"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-229">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-230'
	>
	<li><strong>Restrict permissions:</strong> only grant access that is <strong>absolutely required</strong>. Avoid giving AI full control over sensitive apps like password managers or financial tools.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-section-intro" data-id="es-232">
	<div
	class="section-intro block-section-intro__section-intro section-intro__divider--down section-intro--no-paragraph"
	data-id="es-233"
	 data-type='default'>
	
	
			<div class="section-intro__inner">
			<h2	class='typography typography--size-36-text js-typography section-intro__title'
	data-id='es-234'
	>
	Proceed with Caution</h2>
			<div class="section-intro__wrap">
				<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__as-link btn__icon-position--right section-intro__button js-block-section-intro-button"
	data-id="es-235"
	>
		<div class="btn__inner">
							
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-237'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>			</div>
		</div>
	
			<hr class="section-intro__divider" aria-hidden="true" />
	</div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-241"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-239">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-240'
	>
	Given the rise of lookalike installers and “agent” add-ons, verify sources rigorously before installing anything. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-244"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-242">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-243'
	>
	AI agents are here to stay, but until secure-by-default practices (authentication, least privilege, hardened networking, and auditable controls) become standard, the safest mindset is simple:<strong> If it can operate on your system, it can compromise it.</strong></p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/openclaw-moltbot-clawdbot-viral-ai-sidekick/">OpenClaw: Viral AI Sidekick That Puts You and Your Data at Risk</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19273649https://infinum.com/uploads/2025/12/img-databricks-hero-min.webp</url>
				</image>
				<title>From RAG to Riches: Strengthening Your Cloud AI Foundation with Databricks</title>
				<link>https://infinum.com/blog/scaling-ai-with-databricks/</link>
				<pubDate>Tue, 13 Jan 2026 16:32:40 +0000</pubDate>
				<dc:creator>Nikola Miladinović</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19273649</guid>
				<description>
					<![CDATA[<p>When AI workloads scale, cloud-native tools fall short on governance, versioning, and observability. Databricks fills those gaps without replacing your cloud.</p>
<p>The post <a href="https://infinum.com/blog/scaling-ai-with-databricks/">From RAG to Riches: Strengthening Your Cloud AI Foundation with Databricks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-361"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-247">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-250"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-248">
	<p	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-249'
	>
	<strong>Your RAG system works great until it doesn&#8217;t. As AI workloads scale, cloud-native tools begin to show cracks in governance, versioning, and observability. We explore how Databricks fills these gaps without replacing your existing AWS or Azure infrastructure.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-253"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-251">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-252'
	>
	Most teams already run reliable AI workloads on AWS or Azure. These platforms come with mature services that power modern production systems. Azure OpenAI, Cognitive Search, Blob Storage, AWS Bedrock, OpenSearch, and S3 all support high-quality RAG architectures and handle identity, networking, scaling, and operational reliability with ease.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-256"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-254">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-255'
	>
	But as AI systems grow, technical demands increase, data volumes expand, new document sources emerge, multiple teams work with the same information, and models evolve more frequently. That’s when cracks start to show. Cloud-native tools, built primarily for storage, compute, and serving, struggle to keep up. They lack unified governance, lineage tracking, and transformation pipelines needed to maintain consistency across growing AI workloads. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-259"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-257">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-258'
	>
	The challenge then shifts from building a functional RAG system to orchestrating a governed data foundation, exactly what <strong><a href="https://infinum.com/artificial-intelligence/custom-solutions/">custom AI solutions</a></strong> are designed to address.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-261"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-highlighted-text">
	<p	class='typography typography--size-36-text js-typography block-highlighted-text__typography'
	data-id='es-260'
	>
	At Infinum, we use Databricks as part of our <strong><a href="https://infinum.com/artificial-intelligence/data-engineering/">data engineering practice</a></strong> to future-proof our clients&#8217; AI architecture. We&#8217;ll walk you through its core capabilities, <em>brick by brick</em>, to show you how they work together to help you scale your cloud AI with confidence.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-264"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-262">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-263'
	>
	<strong>Unity Catalog: one layer to rule them all (your data, models, and vectors)</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-267"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-265">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-266'
	>
	<a href="https://www.databricks.com/product/unity-catalog" target="_blank" rel="noreferrer noopener">Unity Catalog</a> is the central governance and metadata layer of the Databricks platform. It brings data, models, vector indexes, and functions under a single, consistent structure, so everything is defined, tracked, and secured in one place. This means simplified permission management and the elimination of fragmentation caused by different services each maintaining their own access rules.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-270"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-268">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-269'
	>
	 Unity Catalog also automatically captures lineage, making it easy to trace how data flows through each stage of your AI pipeline, from ingestion to preprocessing, embedding, retrieval, and inference.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-273"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-271">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-272'
	>
	The result is a unified and predictable governance model that reduces complexity and supports reliable AI development across teams and cloud environments.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-276"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-274">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-275'
	>
	<strong>From unversioned storage to reproducible data with Delta Lake</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-279"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-277">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-278'
	>
	With governance handled by Unity Catalog, the next layer to stabilize is storage itself. RAG systems thrive on structure and stability. But in practice, documents change frequently, models are retrained, and embeddings are regenerated. Without versioning and transactional integrity, it’s hard to explain model behavior or validate changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-282"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-280">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-281'
	>
	Delta Lake solves this challenge by layering ACID guarantees, schema enforcement, and time travel on top of cloud storage. Each Delta table becomes a versioned source of truth for both structured data from databases and unstructured data like PDFs and HTML. Ingestion becomes predictable instead of brittle. Teams can replay experiments without guessing which files existed at a given point in time. Even unstructured content can be governed just like structured tables, using managed volumes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-285"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-283">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-284'
	>
	For teams prioritizing reproducibility and transparency, Delta Lake adds the versioning and transactional guarantees that object storage alone cannot provide.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-288"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-286">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-287'
	>
	<strong>Why retrieval belongs next to your data</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-291"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-289">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-290'
	>
	With stable, versioned data in place, the next challenge is fast, reliable retrieval. Some engineering teams choose to complement their existing retrieval stack with Databricks Vector Search, especially when co-locating retrieval with the underlying data provides a performance or governance advantage. Integrating retrieval into the lakehouse platform offers several benefits:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-294"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-292">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-293'
	>
	<li><strong>Synchronized indexes: </strong>Vector indexes stay in sync with the Delta tables that feed them.</li><li><strong>Automatic embedding updates:</strong> Embeddings can be configured to refresh automatically when source documents change.</li><li><strong>Lower latency:</strong> Retrieval queries run in the same compute environment as the data, reducing round-trip times and response times.</li><li><strong>Consistent governance:</strong> Indexes inherit permissions, lineage, and catalog rules, keeping access control and tracking consistent.</li><li><strong>Easier evaluation workflows: </strong>Co-located retrieval is ideal for comparing embedding models or running offline simulations to detect drift.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-297"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-295"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-296">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2026/01/in-article-databricks_correction-2-1400x753.webp				media='(max-width: 699px)'
				type=image/webp								height="753"
												width="1400"
				 />
								
			<source
				srcset=https://infinum.com/uploads/2026/01/in-article-databricks_correction-2-2400x1291.webp				media='(max-width: 1199px)'
				type=image/webp								height="1291"
												width="2400"
				 />
												<img
					src="https://infinum.com/uploads/2026/01/in-article-databricks_correction-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1338"
															width="2488"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-300"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-298">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-299'
	>
	Unity Catalog handles governance, Delta Lake tracks every version from raw files to embeddings, and Databricks Vector Search continuously syncs with your data as it changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-303"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-301">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-302'
	>
	For teams focused on performance, governance, and evaluation, this level of integration adds speed and structure to otherwise complex retrieval pipelines.<strong><br />
</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-306"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-304">
	<h3	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-305'
	>
	<strong>Keep your models where your data is</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-309"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-307">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-308'
	>
	Getting data and retrieval right is only part of the equation. Now’s the time to plug in the models.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-312"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-310">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-311'
	>
	Databricks Model Serving can help you deploy open-source foundation models, fine-tune custom variants, or run embedding models directly alongside their data, without bolting on separate infrastructure. Whether you&#8217;re working with large language models for generative AI or specialized embedding models for your RAG application, everything remains connected through Unity Catalog.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-313">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-314'
	>
	You can track the entire lifecycle of a model from initial training to production deployment. This enables a multi-model strategy, allowing you to select the best tools for each use case without introducing operational complexity.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-318"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-316">
	<h3	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-317'
	>
	<strong>No more duct-taping your AI pipelines together</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-321"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-319">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-320'
	>
	Modern retrieval-augmented generation workflows require more than just storage and compute. They need orchestration, monitoring, and continuous improvement loops. Databricks provides integrated tooling for the entire RAG architecture:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-324"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-322">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-323'
	>
	<li><strong>AI Playground:</strong> Quickly prototype and test different foundation models and prompts in an interactive environment. Experiment with how generative AI models respond using context from your data.</li><li><strong>Mosaic AI Agent Framework:</strong> Build <a href="https://infinum.com/artificial-intelligence/agent-development/" id="https://infinum.com/artificial-intelligence/agent-development/">intelligent agents</a> that go beyond simple Q&amp;A. These agents can perform complex, multi-step tasks by querying structured data, retrieving documents from vector stores, and synthesizing answers. For a deeper look at how agents connect to external systems, see our overview of <strong><a href="https://infinum.com/blog/model-context-protocols-mcp-ai-enabled-businesses/">Model Context Protocol and AI-enabled businesses</a></strong>.</li><li><strong>Databricks Workflows:</strong> Long-lived pipelines that ingest documents, clean them, segment them, embed them, index them, and validate them, all within the lakehouse. Keeping data-intensive steps in one place eliminates cross-service coordination overhead.<br />
</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-327"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-325">
	<h3	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-326'
	>
	<strong>You can’t improve your system if you can’t observe it</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-330"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-328">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-329'
	>
	As RAG systems mature, observability becomes just as critical as modeling itself. Retrieval performance shifts gradually. Embeddings drift as data evolves. Large language model answers change with new versions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-333"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-331">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-332'
	>
	<a href="https://www.databricks.com/product/machine-learning/lakehouse-monitoring" target="_blank" rel="noreferrer noopener">Lakehouse Monitoring</a> lets you track everything from data quality to model behavior, all in one place. Instead of piecing together logs across disconnected services, you get a single, consolidated view of AI behavior in production, which pairs well with <strong><a href="https://infinum.com/blog/ai-data-visualization/">AI data visualization</a></strong> approaches for surfacing those insights to stakeholders.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-336"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-334"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-335">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2025/12/in-article-databricks-3-novo-1400x753.webp				media='(max-width: 699px)'
				type=image/webp								height="753"
												width="1400"
				 />
								
			<source
				srcset=https://infinum.com/uploads/2025/12/in-article-databricks-3-novo-2400x1291.webp				media='(max-width: 1199px)'
				type=image/webp								height="1291"
												width="2400"
				 />
												<img
					src="https://infinum.com/uploads/2025/12/in-article-databricks-3-novo.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1338"
															width="2488"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-339"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-337">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-338'
	>
	A user query is enriched with relevant context from Vector Search, answered by a large language model, and continuously evaluated through Lakehouse Monitoring to ensure data quality, retrieval relevance, and response reliability.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-342"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-340">
	<h3	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-341'
	>
	<strong>A question every AI team should ask </strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-345"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-343">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-344'
	>
	If your AI workload doubled in size tomorrow, would your current data and governance structures scale with the same confidence as your application layer?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-348"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-346">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-347'
	>
	If the answer isn’t a clear yes, it might be time to lay a stronger foundation with Databricks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-350"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-highlighted-text">
	<p	class='typography typography--size-36-text js-typography block-highlighted-text__typography'
	data-id='es-349'
	>
	<strong><strong>Introducing Databricks into an existing environment is not a platform replacement. It is an architectural enhancement that consolidates governance, data reliability, model lifecycle management, and observability. </strong></strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-353"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-351">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-352'
	>
	The underlying cloud continues to operate application and networking layers, while Databricks provides the durable, governed data foundation needed for long-term AI operations. With <a href="https://6sense.com/tech/big-data-analytics/databricks-market-share" target="_blank" rel="noreferrer noopener">Databricks capturing ~17% of the data warehouse market</a> as of November 2025, its role in enterprise AI infrastructure continues to grow.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-356"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-354">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-355'
	>
	If you&#8217;re ready to accelerate your RAG architecture or take the next leap in your AI platform, <a href="https://infinum.com/artificial-intelligence/" id="https://infinum.com/artificial-intelligence/" target="_blank" rel="noreferrer noopener">our team can help you build a modern, scalable foundation designed for long-term success.</a></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-359"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-357">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-358'
	>
	See how we built a <strong><a href="https://infinum.com/work/midtown-business-intelligence-platform/">real-time data intelligence platform for Midtown Athletic Club</a></strong> as an example of data engineering in practice.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/scaling-ai-with-databricks/">From RAG to Riches: Strengthening Your Cloud AI Foundation with Databricks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19272193https://infinum.com/uploads/2025/11/img-GPT-apps.webp</url>
				</image>
				<title>Your Brand Needs a ChatGPT App Strategy, Now</title>
				<link>https://infinum.com/blog/apps-in-chatgpt-and-the-apps-sdk/</link>
				<pubDate>Tue, 11 Nov 2025 17:27:03 +0000</pubDate>
				<dc:creator>Branimir Akmadža</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19272193</guid>
				<description>
					<![CDATA[<p>The new era of apps is conversational. ChatGPT-native apps are redefining how users discover, interact with, and transact with digital products, and Infinum is ready to help brands lead this shift.</p>
<p>The post <a href="https://infinum.com/blog/apps-in-chatgpt-and-the-apps-sdk/">Your Brand Needs a ChatGPT App Strategy, Now</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[

<div
	class="wrapper js-table-of-contents-data"
	data-id="es-379"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-362">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-365"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-363">
	<p	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-364'
	>
	<strong>OpenAI’s new Apps SDK unlocks a powerful new frontier where apps live inside ChatGPT – interactive, real-time, and seamlessly part of natural conversation. This shift is going to redefine how customers discover, interact with, and purchase digital products. And it’s a big deal.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-368"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-366">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-367'
	>
	There are moments in tech when everything changes: the rise of the web, the move to the cloud, the boom of app stores. We believe we&#8217;re witnessing the next one: apps inside ChatGPT.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-371"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-369">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-370'
	>
	<strong>What are the apps inside ChatGPT, and how do they work?</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-374"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-372">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-373'
	>
	OpenAI&#8217;s new <a href="https://openai.com/index/introducing-apps-in-chatgpt/" target="_blank" rel="noreferrer noopener">Apps SDK allows developers to build native apps</a> that live inside the ChatGPT interface, enabling users to transact, explore, and interact through natural language. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-377"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-375">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-376'
	>
	Instead of asking users to visit your site, download your app, or fill out a form, you’ll be able to meet them where they already are: inside ChatGPT, right in the flow of conversation.</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-382"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-380"
	 data-media-type='video'>

	<div class="video__wrapper" data-id="es-381">
		<video
		class="video block-media__video js-video js-block-media-video video--cursor-takeover-use"
		 loop autoplay playsinline muted preload='metadata'>
		<source  src='https://infinum.com/uploads/2025/11/Domi-Chat-GPT-2.mp4' type='video/mp4' />	</video>
	</div></div></div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-400"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-383">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-387"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-384"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
					</div>

		<div class="intro-label card-simple__outro-label intro-label__line-type--outro" data-id="es-385">
	<p	class='typography typography--size-14-text-roman js-typography intro-label__outro-label'
	data-id='es-386'
	>
	WELCOME TO THE ERA OF CHATGPT APPS.</p></div>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-390"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-388">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-389'
	>
	Whether users are booking a trip, checking their finances, or buying a product, the entire customer journey happens in one interface: fast, intuitive, and frictionless. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-392"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-highlighted-text">
	<p	class='typography typography--size-36-text js-typography block-highlighted-text__typography'
	data-id='es-391'
	>
	<strong>For users, it means fewer redirects and smoother interactions. For brands, it opens up a new channel, a new revenue stream, and a more direct way to turn interest into action. </strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-395"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-393">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-394'
	>
	At Infinum, we’ve been building mobile and web apps for 20 years. We know how to work with app stores, backend platforms, complex UX, and <a href="https://infinum.com/artificial-intelligence/agent-development/" id="https://infinum.com/artificial-intelligence/agent-development/">intelligent, agentic automation</a>. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-398"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-396">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-397'
	>
	ChatGPT Apps feel like a natural next step, and we are ready to help you claim a place in the new AI-native web. </p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-426"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-401">
	

</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-404"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-402">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-403'
	>
	<strong>Why GPT Apps are a turning point for digital experiences</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-407"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-405">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-406'
	>
	ChatGPT is no longer just a place to ask questions.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-410"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-408">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-409'
	>
	With over<strong> </strong><a href="https://techcrunch.com/2025/10/06/sam-altman-says-chatgpt-has-hit-800m-weekly-active-users/" target="_blank" rel="noreferrer noopener">800 million weekly ChatGPT users</a>, it’s quickly becoming a connective layer of the internet, bringing together natural information, easily accessible information, and now services into one unified flow. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-413"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-411">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-412'
	>
	Success now means being genuinely useful at the exact moment of need, not the loudest voice in the room.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-418"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-414">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-415'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-416'
	>
	<strong>People don’t search for answers anymore – they expect to ask and get them instantly. With </strong><a href="https://www.capgemini.com/wp-content/uploads/2019/09/Report-%E2%80%93-Conversational-Interfaces_Web-Final.pdf?utm_source=chatgpt.com"><strong>74% of consumers</strong></a><strong> embracing chat and voice assistants, brands have a once-in-a-generation opportunity to capture first-mover advantage, define the new standard of customer experience, and be truly innovative in their vertical.</strong></p>
		<div class="blockquote__caption-wrap">
			<div	class='typography typography--size-12-text-roman js-typography blockquote__caption'
	data-id='es-417'
	>
	KASPER KUIJPERS, FOUNDER &amp; CTO OF YOUR MAJESTY, PART OF INFINUM<br />
</div>		</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-421"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-419">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-420'
	>
	And while it was only a matter of time before ChatGPT moved beyond search and became a platform for doing, this isn’t happening in isolation.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-424"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-422">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-423'
	>
	Microsoft Copilot, Google Gemini, and Meta’s AI efforts are all moving toward embedding services into conversational AI. But OpenAI’s ChatGPT is leading the way with native app capabilities.</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-432"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-427">
	

</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-430"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-428">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-429'
	>
	<strong>What GPT Apps can do for your business</strong></h2></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-485"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="grid block-grid__grid" data-id="es-484">
	
<div class="block-grid-item" data-id="es-433">
	

</div>

<div class="block-grid-item" data-id="es-443">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-435"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<hr
	class="block-divider"
	data-id="es-434"
	aria-hidden="true" />	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-438"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-436">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-437'
	>
	1</p>	<div class="bullet__content">
			</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-442"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-439"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-440'
	>
	<strong>Get discovered at the right moment</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-441'
	 id='es-439-paragraph'>
	ChatGPT actively recommends apps based on users&#8217; requests. Your brand can appear in conversations that match your offer, opening an organic path to discovery.</p>	</div>
</div>	</div>
</div>

<div class="block-grid-item" data-id="es-453">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-445"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<hr
	class="block-divider"
	data-id="es-444"
	aria-hidden="true" />	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-448"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-446">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-447'
	>
	2</p>	<div class="bullet__content">
			</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-452"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-449"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-450'
	>
	<strong>Reduce friction to boost conversions</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-451'
	 id='es-449-paragraph'>
	No downloads, no redirects, just a question and an answer. Embedding your product or service directly in the conversation shortens the conversion funnel.<br />
</p>	</div>
</div>	</div>
</div>

<div class="block-grid-item" data-id="es-463">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-455"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<hr
	class="block-divider"
	data-id="es-454"
	aria-hidden="true" />	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-458"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-456">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-457'
	>
	3</p>	<div class="bullet__content">
			</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-462"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-459"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-460'
	>
	<strong>Build a high-intent revenue stream</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-461'
	 id='es-459-paragraph'>
	Unlike traditional ads that try to create interest, GPT Apps connect you with people who already have it. You’re meeting users right when they’re expressing a need, turning intent into action.</p>	</div>
</div>	</div>
</div>

<div class="block-grid-item" data-id="es-473">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-465"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<hr
	class="block-divider"
	data-id="es-464"
	aria-hidden="true" />	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-468"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-466">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-467'
	>
	4</p>	<div class="bullet__content">
			</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-472"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-469"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-470'
	>
	<strong>Shape the market as an early mover</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-471'
	 id='es-469-paragraph'>
	Like in the early days of the App Store, early adopters will shape expectations, gain visibility, and build loyalty, all while unlocking opportunities for new kinds of applications and businesses to emerge.<br />
</p>	</div>
</div>	</div>
</div>

<div class="block-grid-item" data-id="es-483">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-475"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<hr
	class="block-divider"
	data-id="es-474"
	aria-hidden="true" />	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-478"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--black block-bullet__bullet" data-id="es-476">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-477'
	>
	5</p>	<div class="bullet__content">
			</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-482"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-479"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-480'
	>
	<strong><strong>Learn from real interactions</strong><br />
</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-481'
	 id='es-479-paragraph'>
	Every conversation tells you something: what users want, where they drop off, and how you can improve their experience.<strong> </strong></p>	</div>
</div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-518"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-486">
	

</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-489"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-487">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-488'
	>
	<strong>What you can build inside ChatGPT Apps</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-492"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-490">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-491'
	>
	ChatGPT Apps combine the best of conversation and interactivity, creating experiences that feel both natural and capable. Here’s what you can build:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-496"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-493">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-494'
	>
	<strong><strong><strong>Conversational commerce experiences</strong></strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-495'
	>
	Let users discover, compare, and purchase products directly in chat. Offer personalized recommendations, real-time inventory checks, and seamless checkout flows. <br />
<br />
For bonus points, let users delegate actions like “If this laptop’s price drops below X, buy it.” The agent can track prices and automatically execute approved actions.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-500"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-497">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-498'
	>
	<strong><strong><strong><strong>Personalized recommendations, booking, and scheduling</strong></strong></strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-499'
	>
	Combine AI with your business logic to provide custom suggestions: products, learning paths, travel plans, or wellness routines tailored to each user’s needs. <br />
<br />
Building off of recommendations, allow users to book appointments, trips, rentals, or restaurant tables through simple conversation. With calendar integrations and smart prompts, booking becomes effortless.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-504"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-501">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-502'
	>
	<strong><strong><strong><strong><strong>Data analysis &amp; visualization</strong></strong></strong></strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-503'
	>
	Let users analyze personal or business data: spending, health, traffic, engagement, and more, and get instant visualizations, comparisons, and insights.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-508"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-505">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-506'
	>
	<strong><strong><strong><strong><strong><strong>Configuration &amp; support</strong></strong></strong></strong></strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-507'
	>
	Turn FAQs, troubleshooting, and account management into guided conversational flows. Users can set up services, customize products, solve issues, update details, or access information without switching channels or contacting support.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-512"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-509">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-510'
	>
	<strong><strong><strong><strong><strong><strong><strong>Real-time transactions</strong></strong></strong></strong></strong></strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-511'
	>
	Let users complete actions like money transfers, document signing, or file uploads directly in ChatGPT conversations.<br />
</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-516"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-513">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-514'
	>
	<strong><strong><strong><strong><strong><strong><strong><strong>Microlearning &amp; training</strong></strong></strong></strong></strong></strong></strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-515'
	>
	Deliver short, interactive lessons for education, compliance, or professional development, perfect for learning in context or on the go.</p>	</div>
</div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-524"
	 data-animation-target='inner-items'>
		
			<div class="block-columns" data-id="es-523">
	
<div class="block-column" data-id="es-522">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-521"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-519"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-520">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2025/11/gpt-app-2-1400x735.webp				media='(max-width: 699px)'
				type=image/webp								height="735"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2025/11/gpt-app-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1260"
															width="2400"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>
</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-530"
	 data-animation-target='inner-items'>
		
			<div class="block-columns" data-id="es-529">
	
<div class="block-column" data-id="es-528">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-527"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-525"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-526">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2025/11/gpt-app-3-new-1400x735.webp				media='(max-width: 699px)'
				type=image/webp								height="735"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2025/11/gpt-app-3-new.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1260"
															width="2400"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>
</div>
</div>	</div>

<div
	class="wrapper"
	data-id="es-554"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-531">
	

</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-534"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-532">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-533'
	>
	<strong>Which industries can benefit from Apps inside ChatGPT?</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-537"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-535">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-536'
	>
	While <strong>retail and ecommerce </strong>are the obvious front-runners, because of the direct path from browsing to purchase, any business offering a product or service can benefit from GPT-native experiences.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-540"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-538">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-539'
	>
	<strong>Travel services</strong> can handle <strong>accommodation, car rentals, ticketing, and dining </strong>booking, confirmations, and itinerary changes through natural queries. In<strong> finance and insurance,</strong> users can analyze spending, receive optimization advice, or complete policy onboarding, all without forms or separate logins.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-543"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-541">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-542'
	>
	In <strong>healthcare,</strong> apps can track metrics from wearables and suggest personalized health actions or recommend lifestyle adjustments. For <strong>education,</strong> GPT-native apps can analyse lessons and learning materials, generate study plans, and adapt based on progress. Even <strong>real estate, legal, and public services </strong>can use this channel to offer instant document reviews, local insights, or access to experts. And with the<strong> Internet of Things, </strong>GPT-native experiences can bridge voice, sensors, and automation, letting users control, monitor, and optimize connected devices just by asking.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-546"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-544">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-545'
	>
	The unifying theme? If your customers can ask for it, we can build an experience for it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-549"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-547">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-548'
	>
	<strong>How to prepare for ChatGPT App integration</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-552"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-550">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-551'
	>
	ChatGPT App development takes both strategic readiness and technical execution. We recommend focusing on speed, ROI, and user experience. </p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-608"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div data-id="es-603" class="block-horizontal-manual-carousel js-block-horizontal-manual-carousel block-horizontal-manual-carousel__align-items--top">
	<div class="block-horizontal-manual-carousel__container block-horizontal-manual-carousel__container--gutter-default js-block-horizontal-manual-carousel-container">
		<div class="cursor-takeover block-horizontal-manual-carousel__cursor-takeover" data-id="es-604">
		<div class="cursor-takeover__cursor js-block-horizontal-manual-carousel-cursor-takeover block-horizontal-manual-carousel__cursor">
		<div class="cursor-takeover__wrap">
			<i
	class="icon cursor-takeover__drag-left icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-left-16' data-id='es-605'>
	<svg height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g fill='none' fill-rule='evenodd' stroke='currentColor' stroke-width='2' transform='matrix(-1 0 0 1 17 0)'><g transform='translate(0 2)'><path d='m.5 5.99999 14 .00001'/><path d='m9.23352.7251 5.97848 5.97852'/><path d='m9.23352 11.2744 5.97848-5.9785'/></g></g></svg></i><i
	class="icon cursor-takeover__drag-right icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-606'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>
			<div class="cursor-takeover__circle js-block-horizontal-manual-carousel-cursor-takeover-circle" aria-hidden="true">
				<p	class='typography typography--size-12-text typography--uppercase js-typography cursor-takeover__label'
	data-id='es-607'
	>
	drag</p>			</div>
		</div>
	</div>
	</div>		
<div class="block-carousel-item" data-id="es-562">
	
<div class="block-typography" data-id="es-555">
	<p	class='typography typography--size-14-text-roman js-typography block-typography__typography'
	data-id='es-556'
	>
	STRATEGIC READINESS<br></p></div>

<div class="block-typography" data-id="es-557">
	<p	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-558'
	>
	01</p></div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-559"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-560'
	>
	<br />
<strong><strong>Identify conversational moments</strong></strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-561'
	 id='es-559-paragraph'>
	Ask: where would chat feel more natural than forms or menus? Review support tickets, drop-off points, and key product flows. Look for places where a simple prompt can replace a multi-step process.<br />
<br />
<em>Need help mapping this? We can guide </em><a href="https://infinum.com/strategy-design/" target="_blank" rel="noreferrer noopener"><em>discovery and user research.</em></a><em> </em></p>	</div>
</div>
</div>

<div class="block-carousel-item" data-id="es-570">
	
<div class="block-typography" data-id="es-563">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-564'
	>
	.</p></div>

<div class="block-typography" data-id="es-565">
	<p	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-566'
	>
	02</p></div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-567"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-568'
	>
	<br />
<strong><strong>Audit your data</strong></strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-569'
	 id='es-567-paragraph'>
	Map out your data sources, formats, and ownership. Check for accuracy, duplication, and sensitive fields that shouldn’t be exposed. Classifying your data early prevents compliance risks and ensures AI works with clean, reliable inputs later on.<br />
</p>	</div>
</div>
</div>

<div class="block-carousel-item" data-id="es-578">
	
<div class="block-typography" data-id="es-571">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-572'
	>
	.</p></div>

<div class="block-typography" data-id="es-573">
	<p	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-574'
	>
	03</p></div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-575"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-576'
	>
	<br />
<strong><strong><strong>Design for conversation</strong></strong></strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-577'
	 id='es-575-paragraph'>
	GPT Apps aren’t websites in a chat box, they’re apps that feel like dialogue. That means designing flows that are short, contextual, and responsive. Focus on natural prompts, clear responses, and interaction patterns that match how people actually talk while staying true to your brand voice.<br />
</p>	</div>
</div>
</div>

<div class="block-carousel-item" data-id="es-586">
	
<div class="block-typography" data-id="es-579">
	<p	class='typography typography--size-14-text-roman js-typography block-typography__typography'
	data-id='es-580'
	>
	TECHNICAL EXECUTION<br></p></div>

<div class="block-typography" data-id="es-581">
	<p	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-582'
	>
	04</p></div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-583"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-584'
	>
	<br />
<strong><strong><strong><strong>Connect your systems</strong></strong></strong></strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-585'
	 id='es-583-paragraph'>
	Your backend probably doesn’t need an overhaul – just a smart integration layer that exposes it through the <a href="https://infinum.com/blog/model-context-protocols-mcp-ai-enabled-businesses/" id="https://infinum.com/blog/model-context-protocols-mcp-ai-enabled-businesses/">Model Context Protocol</a>. By implementing an MCP server around your API, you’ve already done most of the work to join the GPT Apps ecosystem. Then, add secure session handling and real-time sync to enable dynamic content.<br></p>	</div>
</div>
</div>

<div class="block-carousel-item" data-id="es-594">
	
<div class="block-typography" data-id="es-587">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-588'
	>
	.</p></div>

<div class="block-typography" data-id="es-589">
	<p	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-590'
	>
	05</p></div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-591"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-592'
	>
	<br />
<strong style="font-weight: bold">Build and test with the Apps SDK</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-593'
	 id='es-591-paragraph'>
	Set up the Apps SDK, implement OpenAI’s Model Context Protocol, and build a responsive front end. Validate with real user flows, track where users succeed or stall, and iterate quickly to ensure product-market fit.<br />
</p>	</div>
</div>
</div>

<div class="block-carousel-item" data-id="es-602">
	
<div class="block-typography" data-id="es-595">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-596'
	>
	.</p></div>

<div class="block-typography" data-id="es-597">
	<p	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-598'
	>
	06</p></div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-599"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-600'
	>
	<br />
<strong>Prepare for marketplace launch</strong></h3>		</div>

		<p	class='typography typography--size-16-text-roman js-typography card-simple__paragraph'
	data-id='es-601'
	 id='es-599-paragraph'>
	A compelling app isn’t just functional, it’s discoverable. Once your app is ready, we can help refine branding, connect analytics, and ensure conversion optimization post-launch.</p>	</div>
</div>
</div>
	</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-679"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-609">
	

</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-615"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div
	class="block-featured-card js-block-featured-card"
	data-id="es-610"
	data-orientation="vertical">
	<a
		href="https://infinum.com/artificial-intelligence/agent-development/"
		class="block-featured-card__link js-block-featured-card-link"
		>

		
		<div class="block-featured-card__content js-block-featured-card-content">
			<div class="block-featured-card__heading-wrap js-block-featured-card-heading-wrap">
				<h4	class='typography typography--size-36-text js-typography block-featured-card__heading'
	data-id='es-611'
	>
	<strong>Want to move fast? Try our Agentic Sprint and turn the right business use case into a live AI agent prototype in just 10 days.</strong><br />
</h4>			</div>

					</div>

		<button	class="btn btn--color-infinum btn--size-medium btn--width-default btn__icon-position--right block-featured-card__btn js-block-featured-card-btn js-block-featured-card-button"
	data-id="es-612"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-613'
	>
	Learn more</div>		
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-614'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>	</a>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-618"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-616">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-617'
	>
	<strong>Technical foundation for GPT Apps</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-621"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-619">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-620'
	>
	To build a production-ready GPT App, your stack should include:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-624"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-622">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-623'
	>
	<li><strong>Well-documented APIs</strong> for core business functions (e.g., pricing, account access, bookings)</li><li><strong>Secure authentication flows</strong> to manage sessions within the GPT context</li><li><strong>Lightweight frontend assets</strong> (HTML/CSS/JS) that can be rendered inline or full-screen inside ChatGPT</li><li><strong>Structured data sources</strong> like product catalogs or user history for personalized responses</li><li><strong>Integration via Model Context Protocol (MCP)</strong> so ChatGPT understands and responds in sync with your app’s state</li><li><strong>Optional: analytics hooks</strong> to monitor usage, performance, and conversion in real time</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-627"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-625">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-626'
	>
	We help you scope, prioritize, and build what’s needed, starting with use cases that deliver clear user and business value.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-630"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-628">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-629'
	>
	<strong>Why act now?</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-633"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-631">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-632'
	>
	GPT Apps are in early rollout, which means the market is open, but it won’t be for long. Just like early app store adopters or companies that invested early in mobile, the ones who explore ChatGPT apps first will enjoy:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-636"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--black block-bullet__bullet" data-id="es-634">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-635'
	>
	Greater visibility as one of the few apps in a category</h3>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-639"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--black block-bullet__bullet" data-id="es-637">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-638'
	>
	More room to define interaction patterns and user expectations</h3>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-642"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--black block-bullet__bullet" data-id="es-640">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-641'
	>
	Better data, sooner, giving you a head start on optimization</h3>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-645"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-643">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-644'
	>
	By the time this ecosystem matures, brands that moved early will have more traction, more insights, and a stronger position.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-648"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-646">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-647'
	>
	<strong>Should you build in-house or outsource?</strong><br />
</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-651"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-649">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-650'
	>
	If you already have strong in-house teams across AI, UX, and platform engineering, you can probably build internally.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-654"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-652">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-653'
	>
	But if speed, quality, and confidence matter, partnering with a team like<strong> <a href="https://infinum.com/" target="_blank" rel="noreferrer noopener">Infinum</a></strong> can get you further, faster. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-656"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-highlighted-text">
	<p	class='typography typography--size-36-text js-typography block-highlighted-text__typography'
	data-id='es-655'
	>
	For over two decades, we have been building award-winning digital products that succeed in competitive ecosystems, including the Apple App Store, Google Play, and enterprise marketplaces.  </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-659"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-657">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-658'
	>
	We know what it takes to build for evolving platforms. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-662"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-660">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-661'
	>
	Our experience with marketplaces, app standards, and the OpenAI Apps SDK means we can turn early ideas into launch-ready products with clarity and precision.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-665"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-663">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-664'
	>
	<strong>What we offer:</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-668"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-666">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-667'
	>
	<li>Discovery workshops to align goals and identify opportunities</li><li>Rapid prototyping and MVP delivery to test the market quickly</li><li>Full-stack engineering for production-ready GPT Apps</li><li>Post-launch support, analytics, and iteration</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true js-table-of-contents-data"
	data-id="es-671"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-669">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-670'
	>
	<strong>Your move: build where 800M users already are</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-674"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-672">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-673'
	>
	ChatGPT-native apps represent a shift in how users find and use digital products. Infinum is here to help you be part of that change, from strategy to shipping.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-677"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-675">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-676'
	>
	<em><a href="https://infinum.com/contact/" target="_blank" rel="noreferrer noopener">Let’s turn your service into a ChatGPT-native app</a> and get you in front of 800 million users, faster.</em></p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/apps-in-chatgpt-and-the-apps-sdk/">Your Brand Needs a ChatGPT App Strategy, Now</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19270043https://infinum.com/uploads/2025/10/Custom-platform-mobile-app-development-mobile-hero.webp</url>
				</image>
				<title>5 Most Popular Cross Platform Mobile App Development Frameworks</title>
				<link>https://infinum.com/blog/cross-platform-mobile-app-development-guide/</link>
				<pubDate>Thu, 02 Oct 2025 11:38:49 +0000</pubDate>
				<dc:creator>Tanja Bezjak</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19270043</guid>
				<description>
					<![CDATA[<p>Cross-platform mobile app development saves time and cost. Learn the best frameworks, benefits, and challenges to choose the right solution.</p>
<p>The post <a href="https://infinum.com/blog/cross-platform-mobile-app-development-guide/">5 Most Popular Cross Platform Mobile App Development Frameworks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-682"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-680">
	</div>	</div>

<div
	class="wrapper"
	data-id="es-715"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-686">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-685"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-683">
	</div>	</div>
</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-689"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-687">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-688'
	>
	<strong>Cross-platform mobile app development</strong> can help your business in many ways. Fortunately, there are several frameworks that make it easier to <a href="https://infinum.com/enterprise-mobile-app-development-company/">build mobile apps</a> for more than one platform. In fact, there are so many good choices that it might leave you wondering which one to choose. As your <a href="https://infinum.com/custom-app-development-services/" target="_blank" rel="noreferrer noopener">custom mobile app development</a> partners, we would like to help you.<br><br>So, here is our complete cross-platform app development frameworks guide.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-692"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-690">
	<h2	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-691'
	>
	What is cross-platform app development?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-695"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-693">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-694'
	>
	You want your organization’s mobile application to be available to as many people as possible. Cross-platform mobile development, also known as hybrid mobile app development, facilitates this. It is the process of building an app in a way that it runs on both Android and iOS phones.<br><br>As you know, mobile phones have different operating systems (OS). Apple iPhones have iOS, while almost everything else has Android. Since these two are different, an app built for one will not run on the other.<br><br>If you use native <a href="https://infinum.com/mobile-app-development-services/">mobile app development</a>, it would mean building the same product twice—once for each platform, which would increase costs. It is also possible that the finer details of the app might be different, and as a result, users would have an inconsistent experience across devices. With cross-platform mobile application development, you can solve both these problems and a few others.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-698"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-696">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-697'
	>
	Native vs cross-platform app development</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-701"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-699">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-700'
	>
	When building a <a href="https://infinum.com/mobile-web-apps/">mobile app</a>, one of the first choices you face is whether to go native or cross-platform. Each approach has its strengths, and the right one depends on your goals, budget, and timeline.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-704"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-702">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-703'
	>
	Native app development</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-707"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-705">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-706'
	>
	Native app development means creating a dedicated version of your app for each platform — typically iOS and Android. For iOS, you’d use languages like Swift or Objective-C, while for Android you’d use Kotlin or Java to create native apps.<br><br>These mobile apps are designed specifically for one platform and are natively compiled to run on mobile devices.<br><br>The main advantage here is performance. The app is built specifically for one operating system. As such, it runs as smoothly as possible and makes full use of all device features.<br><br>Native apps also deliver the most seamless user experience, since they follow platform-specific design and interaction patterns.<br><br>The downside is cost and time. You are essentially building two apps with two teams. That means more resources and longer timelines. For many businesses, that investment is difficult to justify, which makes hybrid development more tempting.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-710"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-708">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-709'
	>
	Cross-platform app development</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-713"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-711">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-712'
	>
	Cross-platform development uses a single codebase to build apps for both iOS and Android. Instead of writing and maintaining two versions, you develop once and deploy everywhere.<br><br>The benefit is clear: you save on costs by reducing your workload and ensuring consistency between platforms. Your app can reach a larger audience without increasing development effort. <br><br>There is a trade-off, of course. <br><br>Cross-platform frameworks may not always deliver the same level of performance as native. Access to some device-specific features may be limited.<br><br>If your app relies heavily on advanced native features, graphics, or platform-specific capabilities, native development may be the better option. If your goal is to launch a high-quality app quickly and affordably, using cross-platform development tools is often the best option.<br><br>If you do go down the cross-platform development path, you will see several benefits.</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-745"
	>
		
			<div class="block-sticky-element js-block-sticky-element block-sticky-element__positioning-mobile--top block-sticky-element__positioning-tablet--sticky" data-id="es-741">
		<div class="block-sticky-element__sticky-container js-block-sticky-element-sticky-container"  data-animation='slideFade' data-animation-target='inner-items'>
		<div	class="card-simple js-card-simple block-sticky-element__card-simple card-simple__content-align--left"
	data-id="es-742"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h2	class='typography typography--size-52-default js-typography card-simple__heading'
	data-id='es-743'
	>
	Advantages of cross platform mobile application development</h2>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-744'
	 id='es-742-paragraph'>
	We have already touched upon the two main benefits of cross-platform development. But let us look at all of them in detail.</p>	</div>
</div>	</div>
	<div class="block-sticky-element__inner-blocks-container js-block-sticky-element-inner-blocks-container">
		
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-720"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-716">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-717'
	>
	1</p>	<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-718'
	>
	Cost-effective</h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-719'
	>
	<a href="https://infinum.com/blog/how-much-does-it-cost-to-make-an-app/">Building an application </a>is a time- and resource-intensive process. The development team needs to understand your needs to plan the product. They then identify the technology stack that works best for it. Once the planning is complete, it is built and then tested, often several times. This is before the app is even deployed.<br><br>Now imagine doing this twice in tandem.<br><br>Cross-platform development makes it possible to build mobile apps once and release them on different mobile platforms such as Android and iOS. This reduces time and cost compared to native.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-725"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-721">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-722'
	>
	2</p>	<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-723'
	>
	Consistent</h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-724'
	>
	As a brand, you want all your customers to have the same experience across the board. If someone goes to your website, they should see the same branding and appearance, regardless of which browser they use.<br><br>It is the same for your mobile app.<br><br>All customers, whether they are on Android or iOS or Windows phones, should get the same look and features in their web apps. However, two teams developing two versions of the same product might not be able to deliver absolutely identical results. And, it will be two teams because Android developers and iOS developers usually focus on their area of expertise.<br><br>A single design system ensures your mobile UI looks the same across mobile devices, retaining the benefits of native performance where possible.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-730"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-726">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-727'
	>
	3</p>	<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-728'
	>
	Time to market</h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-729'
	>
	If you want consistency in your mobile application while working with two teams, they would need to communicate and coordinate. Without this collaboration, you will end up with two product versions that do not match up. On the other hand, effective coordination between developers will result in delays.<br><br>Using a single development framework that uses shared logic allows you to build faster and publish simultaneously to the app store on both platforms.<br><br>If you are validating an idea, this is a much more efficient way to develop a minimum viable product (MVP). The MVP goes out into the market and is available to both sets of users at once. That means you can start collecting <a href="https://infinum.com/blog/google-analytics-love-affair/">analytics data</a> and use that to improve and iterate sooner.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-735"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-731">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-732'
	>
	4</p>	<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-733'
	>
	Updates</h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-734'
	>
	Once your application has been released, you cannot just forget about it. It has to be maintained and updated regularly. Any bugs discovered post-launch must be fixed. New features must be added, and <a href="https://infinum.com/blog/software-supply-chain-security/">security patches</a> must be released.<br><br>Again, if it is two different versions, you have twice the amount of work on your hands. Why not unify them and reduce the workload? A unified codebase simplifies the development process and ongoing support.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-740"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-736">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-737'
	>
	5</p>	<div class="bullet__content">
		<h3	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-738'
	>
	Broader user base</h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-739'
	>
	A lot of times, a business decides to save money by developing a product for one operating system first. Usually, it is iOS, but sometimes Android might be prioritized. They release this version and use the income it generates to build a version for the other platform.<br><br>If you do that, you are essentially limiting your market size. And, competition in technology is fierce. If a business rival develops a similar product for both platforms, you risk losing sales.<br><br>Cross-platform app development means you can give all your users—regardless of which platform their phone runs on—a working digital product. The best part? It does not cost you as much to develop and maintain, and it is consistent for everyone.</p>	</div>
</div>	</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-748"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-746"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-747">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2025/10/img-break-mobile.webp				media='(max-width: 699px)'
				type=image/webp								height="1620"
												width="1620"
				 />
								
			<source
				srcset=https://infinum.com/uploads/2025/10/img-break-desktop-2400x900.webp				media='(max-width: 1199px)'
				type=image/webp								height="900"
												width="2400"
				 />
												<img
					src="https://infinum.com/uploads/2025/10/img-break-desktop.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1080"
															width="2880"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-773"
	>
		
			<div class="block-sticky-element js-block-sticky-element block-sticky-element__positioning-mobile--top block-sticky-element__positioning-tablet--sticky" data-id="es-769">
		<div class="block-sticky-element__sticky-container js-block-sticky-element-sticky-container"  data-animation='slideFade' data-animation-target='inner-items'>
		<div	class="card-simple js-card-simple block-sticky-element__card-simple card-simple__content-align--left"
	data-id="es-770"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h2	class='typography typography--size-52-default js-typography card-simple__heading'
	data-id='es-771'
	>
	Popular frameworks for cross-platform mobile app development</h2>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-772'
	 id='es-770-paragraph'>
	There are several frameworks for cross-platform mobile development that make it possible to write code once and deploy it across iOS and Android. Each comes with its own strengths and ideal use cases. <br><br>Here are some of the best hybrid app development frameworks.</p>	</div>
</div>	</div>
	<div class="block-sticky-element__inner-blocks-container js-block-sticky-element-inner-blocks-container">
		
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-752"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-749"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-750'
	>
	React Native</h3>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-751'
	 id='es-749-paragraph'>
	Created by Meta, <a href="https://infinum.com/blog/react-project-structure/">React Native</a> is one of the most widely used frameworks in this space. It is an open-source mobile application development framework that uses JavaScript and is based on React. React Native allows developers to reuse components and ship to multiple platforms with minimal friction.<br />
<br />
This framework is able to deliver apps that feel close to native in terms of performance and design. Plus, it is supported by a vast ecosystem of plugins and a large developer community.<br />
<br />
However, its performance might be affected in the case of complex user interfaces or apps requiring access to advanced native modules. And, <a href="https://infinum.com/blog/best-ios-libraries-2024/">third-party libraries</a> must be carefully vetted for security.<br />
<br />
Despite this, React Native remains a strong choice for apps where speed and user experience matter.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-756"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-753"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-754'
	>
	Flutter</h3>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-755'
	 id='es-753-paragraph'>
	<a href="https://infinum.com/mobile-web-apps/flutter/">Flutter</a> is a modern declarative cross-platform UI framework from Google that is favored by businesses that need visually consistent and high-performing apps. It uses the Dart programming language and its own rendering engine. Developers can create pixel-perfect interfaces and visuals that look the same across platforms.<br><br>That said, the framework produces larger app sizes than alternatives. It also has a smaller talent pool compared to JavaScript-based solutions. Still, for startups and businesses that want to launch polished MVPs quickly, Flutter is an excellent choice.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-760"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-757"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-758'
	>
	Kotlin &amp; Compose Multiplatform</h3>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-759'
	 id='es-757-paragraph'>
	Backed by JetBrains, Kotlin supports multiplatform development by sharing business logic across platforms while letting teams keep native UIs where they need them. Developers who already use Kotlin for Android can adopt it easily with the help of <a href="https://infinum.com/blog/kotlin-multiplatform-swiftui/">Kotlin Multiplatform</a> documentation. It offers code reusability without sacrificing performance or user experience.<br><br>Compose Multiplatform builds on top of Kotlin Multiplatform as JetBrains’ modern declarative UI framework. It extends the familiar Jetpack Compose approach from Android to iOS, desktop, and the web, allowing teams to share UI code as well as business logic, while still integrating with native APIs when needed.<br><br>The flexibility of Kotlin Multiplatform is powerful, but it comes with higher developer effort if you choose to build UIs natively. Compose Multiplatform reduces some of that effort by enabling a shared UI layer, though its ecosystem is still catching up compared to long-established native toolkits.<br><br>Kotlin Multiplatform’s tooling and community are still maturing. Still, it’s a strong choice for Kotlin-based teams or complex projects that need scalability, fine-grained control, and the option to evolve their shared UI strategy over time.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-764"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-761"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-762'
	>
	Ionic</h3>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-763'
	 id='es-761-paragraph'>
	This is an open-source framework that is built on familiar <a href="https://infinum.com/blog/web-technologies-for-desktop-development/">web technologies</a> like HTML, CSS, and JavaScript. As a result, it appeals to teams with web development expertise.<br><br>Apps developed on this framework can access native device functionality using Capacitor or Cordova. This makes it a flexible option for rapid prototyping or content-driven applications. <br><br>Ionic is easy to learn and integrates well with popular frameworks such as Angular, React, and Vue for building cross-platform apps. The drawback is performance, which often lags behind frameworks like Flutter and React Native. The user experience can also feel less “native.” <br><br>Still, if you need to validate an idea quickly or build simple apps with limited budgets, Ionic is a practical solution.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-768"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-765"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-766'
	>
	Xamarin</h3>		</div>

		<p	class='typography typography--size-20-text-roman js-typography card-simple__paragraph'
	data-id='es-767'
	 id='es-765-paragraph'>
	This framework is used for building apps with C#. Originally owned by Microsoft, it is now evolving into .NET MAUI. For organizations already invested in Microsoft technologies, it offers seamless integration with the wider ecosystem and strong enterprise-grade support.<br><br>Xamarin provides good performance and deep native integration. However, the trade-off is a steeper learning curve and a smaller open-source community compared to Flutter or React Native.<br><br>Its reliability and backing from Microsoft make it the preferred choice for enterprise applications and B2B solutions.<br><br>Each of these frameworks has its place. The best one for your project depends on your priorities.</p>	</div>
</div>	</div>
	</div>
</div>	</div>

<div
	class="wrapper"
	data-id="es-775"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<hr
	class="block-divider"
	data-id="es-774"
	aria-hidden="true" />		</div>
	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-811"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="grid block-grid__grid" data-id="es-810">
	
<div class="block-grid-item" data-id="es-779">
	
<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-776"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h2	class='typography typography--size-36-text js-typography card-simple__heading'
	data-id='es-777'
	>
	Disadvantages of cross-platform app development</h2>		</div>

		<p	class='typography typography--size-18-text-roman js-typography card-simple__paragraph'
	data-id='es-778'
	 id='es-776-paragraph'>
	Developing hybrid apps is not without its challenges. Understanding these drawbacks will help you make an informed decision.</p>	</div>
</div>
</div>

<div class="block-grid-item" data-id="es-785">
	
<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-780">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-781'
	>
	1</p>	<div class="bullet__content">
			</div>
</div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-782"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text-medium js-typography card-simple__heading'
	data-id='es-783'
	>
	Performance limitations</h3>		</div>

		<p	class='typography typography--size-18-text-roman js-typography card-simple__paragraph'
	data-id='es-784'
	 id='es-782-paragraph'>
	While most frameworks offer strong performance, they may not always match the speed and responsiveness of apps built natively. Does your product rely on advanced graphics, heavy animations, or resource-intensive processing? If yes, cross-platform solutions can introduce latency or feel less smooth.</p>	</div>
</div>
</div>

<div class="block-grid-item" data-id="es-791">
	
<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-786">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-787'
	>
	2</p>	<div class="bullet__content">
			</div>
</div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-788"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text-medium js-typography card-simple__heading'
	data-id='es-789'
	>
	Access to native features</h3>		</div>

		<p	class='typography typography--size-18-text-roman js-typography card-simple__paragraph'
	data-id='es-790'
	 id='es-788-paragraph'>
	Platform-specific features include advanced camera controls, AR capabilities, or deep OS-level integrations. These can be harder to implement in a cross-platform framework. In many cases, developers need to build custom “bridges” to tap into native APIs, which increases complexity.</p>	</div>
</div>
</div>

<div class="block-grid-item" data-id="es-797">
	
<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-792">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-793'
	>
	3</p>	<div class="bullet__content">
			</div>
</div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-794"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text-medium js-typography card-simple__heading'
	data-id='es-795'
	>
	User experience differences</h3>		</div>

		<p	class='typography typography--size-18-text-roman js-typography card-simple__paragraph'
	data-id='es-796'
	 id='es-794-paragraph'>
	Although frameworks strive for consistency, the “look and feel” of iOS and Android differ in subtle ways. Native development automatically accounts for these platform conventions. Cross-platform apps risk feeling slightly off to experienced users unless the UI is carefully customized for each platform.</p>	</div>
</div>
</div>

<div class="block-grid-item" data-id="es-803">
	
<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-798">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-799'
	>
	4</p>	<div class="bullet__content">
			</div>
</div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-800"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text-medium js-typography card-simple__heading'
	data-id='es-801'
	>
	App size</h3>		</div>

		<p	class='typography typography--size-18-text-roman js-typography card-simple__paragraph'
	data-id='es-802'
	 id='es-800-paragraph'>
	Certain frameworks tend to generate larger file sizes than native apps, which is not always critical. But if you are targeting users with limited storage space or poor internet connectivity, this can be a drawback.</p>	</div>
</div>
</div>

<div class="block-grid-item" data-id="es-809">
	
<div class="bullet bullet--top bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-804">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-805'
	>
	4</p>	<div class="bullet__content">
			</div>
</div>

<div	class="card-simple js-card-simple block-card__card-simple card-simple__content-align--left"
	data-id="es-806"
	>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h3	class='typography typography--size-24-text-medium js-typography card-simple__heading'
	data-id='es-807'
	>
	Dependency on frameworks</h3>		</div>

		<p	class='typography typography--size-18-text-roman js-typography card-simple__paragraph'
	data-id='es-808'
	 id='es-806-paragraph'>
	A cross-platform solution relies on the framework’s ongoing support and updates. If a framework becomes outdated or loses community support, maintaining and upgrading your app may become more challenging.</p>	</div>
</div>
</div>
</div>	</div>

<div
	class="wrapper"
	data-id="es-813"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<hr
	class="block-divider"
	data-id="es-812"
	aria-hidden="true" />		</div>
	</div>

<div
	class="wrapper"
	data-id="es-831"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-817">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-816"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-814">
	</div>	</div>
</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-820"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-818">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-819'
	>
	How to decide if hybrid development is right for you?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-823"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-821">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-822'
	>
	Choosing between native and cross-platform development is not always straightforward. Both approaches have clear advantages as well as drawbacks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-826"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-824">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-825'
	>
	If you want to build <a target="_blank" rel="noreferrer noopener" href="https://infinum.com/cross-platform-app-development-services/">cross-platform mobile solutions</a> quickly, a top cross-platform framework may be the best solution. But if your product depends on native code and advanced integrations, a native-first strategy might be better.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-829"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-827">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-828'
	>
	The right partner agency can help you choose wisely. At Infinum, our mobile engineers have experience across hybrid mobile, multiplatform mobile, and native projects. <br>Interested in learning more about how Flutter sold the idea of hybrid development to us? Read our blog post: <a href="https://infinum.com/blog/from-native-to-cross-platform/" target="_blank" rel="noreferrer noopener">From Native to Cross-Platform: 10/10 Would Recommend</a>. <br></p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-834"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-832">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-833'
	>
	 </p></div>	</div><p>The post <a href="https://infinum.com/blog/cross-platform-mobile-app-development-guide/">5 Most Popular Cross Platform Mobile App Development Frameworks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19265798https://infinum.com/uploads/2025/05/Enhancing-Embedded-Devices-with-Firmware-Updates-hero.webp</url>
				</image>
				<title>Enhancing Embedded Devices with Firmware Updates</title>
				<link>https://infinum.com/blog/iot-embedded-devices-firmware-updates/</link>
				<pubDate>Mon, 01 Sep 2025 10:31:42 +0000</pubDate>
				<dc:creator>Jurica Martinčević</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19265798</guid>
				<description>
					<![CDATA[<p>Learn how to how to build a reliable update system that keeps your embedded IoT devices running smoothly in the field.</p>
<p>The post <a href="https://infinum.com/blog/iot-embedded-devices-firmware-updates/">Enhancing Embedded Devices with Firmware Updates</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-1020"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-835">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-838"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-836">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-837'
	>
	<strong>From bug fixes to new features, firmware updates are essential for a device’s evolution. Here’s how to build a reliable update system that keeps your embedded IoT devices running smoothly in the field.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-841"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-839">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-840'
	>
	Updating firmware is a critical component in the lifecycle of any embedded IoT device. It provides flexibility during development, but also simplifies support and enables long-term feature evolution. In essence, firmware updates allow these devices to modify their current operational software to fix bugs, improve performance, or introduce new capabilities – like supporting <a href="https://infinum.com/blog/iot-data-business-value/" target="_blank" rel="noreferrer noopener">machine learning models that optimize business processes</a> using real-time IoT inputs.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-844"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-842">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-843'
	>
	Think of firmware as a program on a computer or a smartphone – except it’s designed specifically to run on embedded systems. Firmware updates can be performed wirelessly when a device is connected via Bluetooth or WiFi. This method is known as an Over-the-Air (OTA) update, or more specifically, Firmware Over-the-Air (FOTA), highlighting its remote and seamless execution.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-847"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-845">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-846'
	>
	Problems that firmware updates can solve</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-851"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-848">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-849'
	>
	<strong>Bug fixes</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-850'
	>
	Simple bugs can be addressed through code changes and library upgrades.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-855"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-852">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-853'
	>
	<strong>Introduction of new features</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-854'
	>
	More complex changes that expand device capabilities.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-859"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-856">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-857'
	>
	<strong>Security updates</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-858'
	>
	Resolving critical security issues.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-863"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-860">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-861'
	>
	<strong>Settings changes</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-862'
	>
	Modifying system configurations or default behaviors.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-866"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-864">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-865'
	>
	Potential issues with firmware updates</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-869"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-867">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-868'
	>
	While beneficial, firmware updates can also impose certain risks. If the update contains a bug, or worse, malicious code, it may cause problems with the device:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-873"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-870">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-871'
	>
	<strong><strong>Inability to update again</strong></strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-872'
	>
	Faulty updates may block future installations.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-877"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-874">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-875'
	>
	<strong>Bricked device</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-876'
	>
	Updates can render a device unusable.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-881"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-878">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-879'
	>
	<strong>Malicious firmware</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-880'
	>
	Unauthorized updates can compromise device security.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-884"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-882">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-883'
	>
	It is crucial to approach firmware updates with caution and ensure proper implementation. Otherwise, a poorly executed update might create more problems than it aims to solve.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-887"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-885">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-886'
	>
	How firmware updates work</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-890"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-888">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-889'
	>
	Enabling firmware updates on a device requires certain memory compromises. The device’s non-volatile memory (Flash memory) should be partitioned into three sections:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-894"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-891">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-892'
	>
	1</p>	<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-893'
	>
	Current firmware</h3>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-898"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-895">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-896'
	>
	2</p>	<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-897'
	>
	Update firmware</h3>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-902"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-899">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-900'
	>
	3</p>	<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-901'
	>
	Bootloader</h3>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-905"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-903">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-904'
	>
	The bootloader section can be just large enough to fit the bootloader, while the sections for the current firmware and the update must be equal in size and large enough to store the device firmware.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-908"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-906">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-907'
	>
	To partition the Flash memory properly, a linker script should be used to ensure that the linker does not store parts of the code in the bootloader or update the firmware sections. Additionally, the application code should be compiled to execute from the start of the current firmware section to ensure correct jump addresses when running.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-911"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-909">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-910'
	>
	Bootloader</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-914"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-912">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-913'
	>
	A bootloader is essential for enabling firmware updates on the device. Its primary functions include optional firmware verification, installing new firmware, and jumping to the start of the application code. The firmware verification can be done either in the application code before entering the bootloader or within the bootloader itself. When the device boots, it always goes into the bootloader first.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-917"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-915">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-916'
	>
	The bootloader then checks if there is new firmware to install: if so, it performs the installation and eventually jumps to the start of the application code. Different methods can be used to notify the bootloader that new firmware is available, such as reading a specific Flash memory address set by the application after downloading the firmware.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-920"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-918">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-919'
	>
	Firmware updates involve several key steps:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-925"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-921">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-922'
	>
	1</p>	<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-923'
	>
	<strong>Receiving the firmware</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-924'
	>
	The device receives the new firmware in chunks and saves it in non-volatile memory. This can be done via Bluetooth, WiFi, UART, or CAN. Typically, it is done in the application code to ensure the device remains functional during download, and downtime is kept to a minimum.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-930"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-926">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-927'
	>
	2</p>	<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-928'
	>
	<strong>Verifying the firmware</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-929'
	>
	This step checks if the firmware is valid and authorized, preventing the installation of corrupted or unauthorized firmware that could be malicious.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-935"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-931">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-932'
	>
	3</p>	<div class="bullet__content">
		<h3	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-933'
	>
	<strong>Installing the firmware</strong></h3><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-934'
	>
	The installation process is performed in the bootloader. It involves overriding the current application code with the new firmware, which cannot be done while the application code is running. The bootloader transfers the new firmware from the temporary storage area (update firmware section) to the main operational area (current firmware section) of the Flash memory.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-938"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-936">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-937'
	>
	Remote firmware distribution</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-941"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-939">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-940'
	>
	There are two ways to initiate a firmware update: automatically and manually. The choice of how to start the update depends on the use case and the device&#8217;s connectivity capabilities, which can vary significantly in the IoT space.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-944"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-942">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-943'
	>
	Automatic firmware updates</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-947"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-945">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-946'
	>
	With automatic updates, the device takes charge of connecting to the server, checking for new firmware, and initiating the update. Users don&#8217;t have direct control over starting the update process.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-950"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-948">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-949'
	>
	This approach is suitable for devices with continuous or intermittent connectivity or those with unstable connections. All that&#8217;s needed is to release the firmware update on the server. The device can be configured to start the update based on certain conditions, such as a specific time of day or reaching a particular state.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-953"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-951">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-952'
	>
	Manual firmware updates</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-956"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-954">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-955'
	>
	For a manual update, the user must trigger the firmware update process – highlighting the importance of <a href="https://infinum.com/blog/iot-user-experience/" target="_blank" rel="noreferrer noopener">designing clear, user-friendly interactions in IoT interfaces</a>. This can be done in various ways. It could be initiated by the device itself, using some form of user input available. Alternatively, another device could be used to start the update, or an external device might be employed to initiate the process. This type of update works for all types of devices, regardless of their connectivity, ranging from always connected to never connected.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-959"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-957">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-958'
	>
	Manual updates require user intervention to start the firmware update process. There are several ways to initiate this process:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-962"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-960">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-961'
	>
	<li>Directly on the device itself, using the input methods available</li><li>Through another connected device</li><li>Via external hardware</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-965"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-963">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-964'
	>
	The advantage of manual updates is their versatility – they work with all types of devices regardless of connectivity status, from always-online devices to those with no regular network connection.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-968"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-966">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-967'
	>
	Updating non-connected devices</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-971"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-969">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-970'
	>
	Devices that are only connected on demand can be updated through Bluetooth connectivity solely for firmware updates. In this scenario, the device advertises itself and waits for a connection. The user can connect the device to a smartphone via Bluetooth, download the firmware update file to the smartphone, and then transfer it to the device to start the update.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-974"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-972">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-973'
	>
	Non-connected devices can also be updated manually using wired protocols like UART or CAN, or external storage devices like an SD card. The device can have a specific user input that triggers the firmware reception from the UART, SD card, or other wired protocol. If using UART, CAN, or any other wired protocol, there must be an external device to communicate with the main device being updated and to contain the firmware file.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-977"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-975">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-976'
	>
	Security measures in firmware updates</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-980"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-978">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-979'
	>
	Security is enforced primarily during the firmware validation step. The main goal is to ensure the received firmware is legitimate and free from tampering. Several essential steps fall under this category, including integrity checks, firmware decryption, and firmware signing checks. Some of these operations may involve asymmetric encryption, with the keys needing to be securely stored in encrypted Flash memory or protected against unauthorized access.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-983"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-981">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-982'
	>
	When both firmware encryption and firmware signing are in place, the following keys are typically found on the device:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-987"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-984">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<p	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-985'
	>
	<strong>Device private key</strong></p><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-986'
	>
	This key is known only to the device manufacturer and is used for firmware encryption.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-991"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-988">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<p	class='typography typography--size-20-text js-typography bullet__heading'
	data-id='es-989'
	>
	<strong>Manufacturer public key</strong></p><p	class='typography typography--size-20-text-roman js-typography bullet__paragraph'
	data-id='es-990'
	>
	This key is employed for firmware signing and is made public by the manufacturer.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-994"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-992">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-993'
	>
	Integrity check</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-997"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-995">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-996'
	>
	The integrity check step ensures that the received firmware is error-free during communication, detecting potential issues like bit-flips. The device calculates the hash of the received firmware using methods like md5, and compares it with the hash received along with the firmware. A match indicates that the received firmware is intact and uncorrupted, allowing the device to proceed to the next validation step. This step is crucial for preventing the installation of corrupted firmware that might lead to unexpected behavior.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1000"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-998">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-999'
	>
	Firmware decryption</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1003"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1001">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1002'
	>
	Firmware encryption is the process of encoding the firmware information to prevent unauthorized access to its content. When encrypting the firmware, the device&#8217;s public key is utilized. Upon receiving the firmware, the device uses its private key to decrypt the firmware for further processing.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1006"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1004">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1005'
	>
	Firmware signing check</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1009"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1007">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1008'
	>
	Firmware signing involves encrypting the firmware with the manufacturer&#8217;s private key, which confirms that the firmware comes from the manufacturer. However, it is not practical to encrypt the entire firmware with the private key. Instead, only the firmware hash is encrypted, and cryptographic hash functions like SHA-256 are commonly employed for this purpose. This way, the device can validate the authenticity of the firmware by decrypting the hash using the manufacturer&#8217;s public key.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1012"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1010">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1011'
	>
	The importance of updating firmware</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1015"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1013">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1014'
	>
	As technology advances, digital services constantly evolve. With the continuous introduction of new products featuring the latest technologies and improved features, you can enhance your existing devices by simply updating their firmware, enabling your older hardware to keep up with the latest capabilities.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1018"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1016">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1017'
	>
	<em>This article is adapted from our <a href="https://infinum.com/iot-implementation/" target="_blank" rel="noreferrer noopener">Guide to Successful IoT Implementation</a>, where we cover the technical foundations and strategic considerations behind building modern IoT solutions. For more insights, download the full guide.</em></p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/iot-embedded-devices-firmware-updates/">Enhancing Embedded Devices with Firmware Updates</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19267151https://infinum.com/uploads/2025/07/img-apple-on-device-hero-1.webp</url>
				</image>
				<title>Apple’s Quiet AI Revolution: What On-Device AI Means for the Future of iOS Apps</title>
				<link>https://infinum.com/blog/apple-on-device-ai/</link>
				<pubDate>Mon, 30 Jun 2025 13:10:27 +0000</pubDate>
				<dc:creator>Filip Gulan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19267151</guid>
				<description>
					<![CDATA[<p>Apple’s new On-device AI unlocks powerful, private, and cost-efficient features for iOS apps. Here’s what product teams need to know.</p>
<p>The post <a href="https://infinum.com/blog/apple-on-device-ai/">Apple’s Quiet AI Revolution: What On-Device AI Means for the Future of iOS Apps</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-1189"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1021">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1024"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1022">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-1023'
	>
	WWDC 2025 didn’t bring the loudest fireworks in AI. But make no mistake: <strong>Apple just pulled a strategic move that every product leader should pay attention to.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1027"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1025">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1026'
	>
	While headlines are locked on GPT-4o, Gemini 1.5, and the escalating cloud model race, Apple is taking a different route — one that’s deeply integrated, privacy-centric, and highly relevant for anyone building digital products inside its ecosystem.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1030"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1028">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1029'
	>
	The star of this shift? Apple’s new <strong>Foundation Models Framework.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1033"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1031">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1032'
	>
	<strong>Foundation Models 101</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1036"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1034">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1035'
	>
	At its core, Apple’s Foundation Models Framework gives third-party iOS developers access to Apple’s own generative AI models directly on-device.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1039"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1037">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1038'
	>
	Here are some of the key specs:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1042"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1040">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1041'
	>
	<li>A language model with roughly 3 billion parameters, fine-tuned for Apple Silicon.</li><li>Fully local inference, which means no cloud dependency for most AI tasks.</li><li>Multimodal support, allowing for both text and image inputs, as well as tool invocation.</li><li>Privacy, safety guardrails, and structured output features built-in.</li><li>Deep native integration via Swift and Xcode, where developers can invoke AI features with just a few lines of code.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1045"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1043">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1044'
	>
	Apple isn’t competing directly with GPT-4 or Claude here. Instead, it&#8217;s delivering a highly optimized model specifically designed for real-world iPhone and iPad apps. The developer tooling is where things get especially interesting because Apple is making AI integration far more predictable and production-ready than many off-the-shelf open-source models.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1048"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1046">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1047'
	>
	<strong>Standout developer features</strong><br />
</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1052"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-1049">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1050'
	>
	<strong>Guided Generation:</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1051'
	>
	Developers can generate structured outputs like objects, lists, or JSON using Swift annotations.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1056"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-1053">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1054'
	>
	<strong>Tool Calling:</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1055'
	>
	Models can invoke app-defined functions during generation to pull real-time or app-specific data.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1060"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--dot bullet__color--infinum block-bullet__bullet" data-id="es-1057">
			<div class="bullet__dot"></div>
		<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1058'
	>
	<strong><strong>Safety Guardrails</strong>:</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1059'
	>
	Apple includes built-in content filtering and responsible AI guidelines to ensure outputs remain safe and aligned.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1063"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1061">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1062'
	>
	Put simply: Apple isn&#8217;t just delivering a model — it&#8217;s delivering<strong> an entire AI operating layer baked into iOS.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1066"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1064">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1065'
	>
	For full technical details, Apple’s official <a href="https://developer.apple.com/wwdc25/">WWDC 2025 developer documentation</a> is a must-read.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1069"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1067">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1068'
	>
	<strong>Why this is a big deal (even if it’s not GPT-4)</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1072"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1070">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1071'
	>
	On-device AI isn’t exactly new as a concept. But Apple just made it radically easier to adopt.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1075"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1073">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1074'
	>
	<strong><strong>AI becomes a native OS capability</strong></strong><br />
</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1078"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1076">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1077'
	>
	Think back to when apps first got access to cameras, GPS, or push notifications. Foundation Models mark a similar inflection point. Developers now get direct access to <strong>powerful generative AI inside the iPhone’s operating system</strong>, without the need for complicated APIs, server costs, or compliance headaches.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1081"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1079">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1080'
	>
	In effect, Apple is turning every iPhone into a personal AI computer.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1084"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1082">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1083'
	>
	<strong>Privacy by design</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1087"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1085">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1086'
	>
	<strong>Data never leaves the device.</strong> For product teams building in highly regulated sectors like finance, healthcare, and enterprise SaaS, this is a major advantage. You can now build AI-powered features that analyze personal or sensitive data while keeping everything securely on-device.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1090"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1088">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1089'
	>
	<strong>More predictable AI economics for product teams</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1093"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1091">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1092'
	>
	While many teams are willing to invest heavily in AI innovation, <strong>the long-term economics of AI operations can still influence product roadmaps.</strong> With Foundation Models running on-device, teams avoid paying ongoing fees for third-party APIs, cloud infrastructure, or dedicated inference servers. AI capabilities become part of the app itself, simplifying budgeting and allowing companies to scale features to larger user bases without costs ballooning unpredictably over time.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1096"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1094">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1095'
	>
	<strong>On-device ML models make up for great UX</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1099"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1097">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1098'
	>
	Since models run directly on the device, <strong>AI features become instantly responsive.</strong> There are no network delays, no dependency on server round-trips, and full functionality even when users are offline. Whether someone is flying, commuting underground, or traveling through areas with poor connectivity, <strong>the experience remains smooth and fully available.</strong> For many apps, this level of instant responsiveness doesn’t just improve UX — it unlocks entirely new product possibilities where speed and privacy are non-negotiable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1102"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1100">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1101'
	>
	<strong>Use cases product leaders should explore</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1105"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1103">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1104'
	>
	There’s a couple of months before iOS 26 becomes publicly available, so the real-world applications for Apple&#8217;s Foundation Models are yet to materialize. In theory, these opportunities cut across multiple industries, each with their own relevant on-device AI use cases. Let&#8217;s break it down:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-1106">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-1107'
	>
	1</p>	<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1108'
	>
	<strong>Healthcare</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1109'
	>
	Summarizing patient notes or analyzing personal health data securely on-device</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1115"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-1111">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-1112'
	>
	2</p>	<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1113'
	>
	<strong>Fintech</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1114'
	>
	Parsing financial documents or generating reports with no cloud processing.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1120"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-1116">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-1117'
	>
	3</p>	<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1118'
	>
	<strong>SaaS &amp; productivity</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1119'
	>
	Auto-summarizing meeting notes, emails, or customer tickets offline.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1125"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-1121">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-1122'
	>
	4</p>	<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1123'
	>
	<strong>Consumer apps</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1124'
	>
	Personalized chatbots that work offline (travel, fitness, shopping assistance).</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1130"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="bullet bullet--left bullet__type--number bullet__color--infinum block-bullet__bullet" data-id="es-1126">
	<p	class='typography typography--size-14-text js-typography bullet__dot'
	data-id='es-1127'
	>
	5</p>	<div class="bullet__content">
		<p	class='typography typography--size-24-text js-typography bullet__heading'
	data-id='es-1128'
	>
	<strong>Connected devices &amp; smart home</strong></p><p	class='typography typography--size-16-text-roman js-typography bullet__paragraph'
	data-id='es-1129'
	>
	Voice-controlled assistants that manage schedules, automate routines, or optimize energy use directly on-device without sharing data externally.</p>	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1133"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1131">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1132'
	>
	For developers already experimenting, some early success stories have surfaced on <a href="https://www.reddit.com/r/iOSProgramming/">Reddit’s iOSProgramming forum</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1136"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1134">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1135'
	>
	<strong>Questions product leaders should be asking</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1139"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1137">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1138'
	>
	Apple’s approach comes with some trade-offs that product leaders need to navigate carefully.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1140">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1141'
	>
	<li>What AI-powered features could we build that benefit from privacy and offline functionality?</li><li>Where are we currently incurring cloud AI costs that could be reduced with on-device inference?</li><li>How do we get started? What is the right first feature or prototype to explore with Apple&#8217;s Foundation Models?</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1145"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1143">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1144'
	>
	<strong>Great all around, still not a silver bullet</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1148"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1146">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1147'
	>
	Apple’s approach comes with some trade-offs that product leaders need to navigate carefully.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1151"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1149">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1150'
	>
	<li><strong>The model’s size is limited.</strong> At ~3B parameters, it’s not built for open-ended reasoning or general knowledge.</li><li><strong>It’s not fully open or fine-tunable.</strong> Apple’s black-box approach limits deep customization.</li><li><strong>It’s Apple-exclusive.</strong> Equivalent Android capabilities simply aren’t widely available today.</li><li><strong>Hybrid models may still be necessary</strong> for some advanced use cases.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1154"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1152">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1153'
	>
	In short, this works brilliantly for many domain-specific or app-specific tasks but isn’t intended to replace cloud-based LLMs entirely.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1157"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1155">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1156'
	>
	<strong>Where we see opportunity</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1160"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1158">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1159'
	>
	At Infinum, we see this as one of the most important updates for mobile product development in recent years.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1163"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1161">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1162'
	>
	Why? Because this isn&#8217;t just about adding AI as a feature. <strong>It&#8217;s about creating differentiated experiences</strong> that competitors can’t easily replicate, building trust with privacy-conscious users and enterprise clients, and controlling costs while still delivering highly sophisticated features.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1164">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1165'
	>
	This levels the playing field: you don’t need to be an AI research lab to build intelligent apps. But you do need strategic product expertise, domain-specific prompt engineering, and deep knowledge of Apple&#8217;s AI stack.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1169"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1167">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1168'
	>
	<strong>What comes next?</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1170">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1171'
	>
	Apple devices are becoming exponentially more powerful by the year. With each hardware leap, Apple’s AI capabilities are maturing as well. So you can safely expect this quiet revolution to accelerate.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1173">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1174'
	>
	Users will increasingly<strong> expect AI assistance as a standard part of their apps</strong>, much like they expect biometric logins or dark mode today<strong>.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1176">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1177'
	>
	For product leaders, the smartest move right now is to experiment early, build prototypes, and assess<strong> where on-device AI can create meaningful value.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1181"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1179">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1180'
	>
	If you&#8217;re thinking about how to bring AI features to your iOS product roadmap — while staying cost-efficient, privacy-compliant, and future-proof — this is exactly the right moment to start that conversation.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1184"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1182">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1183'
	>
	Interested in utilizing Apple’s new AI model but not sure where to start? This is where Infinum can add real value: <strong>advisory, rapid prototyping, and hands-on expertise across AI/ML &amp; mobile.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1187"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1185">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1186'
	>
	For those who want to dive even deeper, Apple&#8217;s own <a href="https://machinelearning.apple.com">Machine Learning Research blog</a> offers technical insights into how these models were designed.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/apple-on-device-ai/">Apple’s Quiet AI Revolution: What On-Device AI Means for the Future of iOS Apps</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19266034https://infinum.com/uploads/2025/05/Cobol-2.webp</url>
				</image>
				<title>Is Ruby on Rails Becoming the New COBOL?</title>
				<link>https://infinum.com/blog/is-ruby-on-rails-becoming-the-new-cobol/</link>
				<pubDate>Tue, 27 May 2025 12:29:17 +0000</pubDate>
				<dc:creator>Jaka Šušteršič</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19266034</guid>
				<description>
					<![CDATA[<p>Ruby on Rails was once the hottest ticket in tech. Now it's a cult classic with a loyal crowd. But is it on its way to becoming the next COBOL?</p>
<p>The post <a href="https://infinum.com/blog/is-ruby-on-rails-becoming-the-new-cobol/">Is Ruby on Rails Becoming the New COBOL?</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-1332"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1190">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1193"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1191">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-1192'
	>
	Ruby on Rails used to be the hot band everyone wanted to see live. Now it feels more like a cult classic, still good, still playing, but to a smaller, more devoted crowd. And lately, some folks are wondering: is Rails on the path to becoming the next COBOL?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1194">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1195'
	>
	Yes, <em>that</em> COBOL. The 65-year-old language quietly running billions of lines of code inside banks, governments, and systems nobody wants to touch but everybody needs. On paper, the comparison seems extreme. But look closer, and you’ll start to see the shape of a long tail forming behind Rails. One that looks suspiciously like legacy.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1197">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1198'
	>
	Let’s dig in.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1202"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1200">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1201'
	>
	The rise of two titans</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1205"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1203">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1204'
	>
	COBOL and Ruby on Rails couldn’t be more different in syntax, style, or era. They definitely share one thing though: <strong>both were once the default choice for a generation of developers</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1208"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1206">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1207'
	>
	COBOL, born in 1959, became the backbone of enterprise and government systems by the ’70s. If you’ve ever withdrawn cash, paid taxes, or waited for a check to clear, COBOL probably had something to do with it. Its dominance was complete, and it stuck — not because developers loved it, but because rewriting working software is expensive, risky, and often unnecessary.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1211"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1209">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1210'
	>
	Fast forward to the 2000s. Enter Rails: elegant, opinionated, and built for speed. DHH dropped <em>convention over configuration</em> like a mic, and the web dev world listened.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1214"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1212">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1213'
	>
	From 2005 to 2014, Rails was the framework of choice for startups, SaaS tools, and hacker weekends. Twitter, GitHub, Shopify, and Basecamp all bet big on it. For a while, every bootcamp taught it, every founder loved it, and every developer blog had a hot take on ActiveRecord callbacks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1217"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1215">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1216'
	>
	It was a golden era. Until it wasn’t.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1220"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1218">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1219'
	>
	How Rails stacks up these days</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1223"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1221">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1222'
	>
	Spoiler alert: not like it used to.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1226"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1224">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1225'
	>
	Once the backbone of every hot startup stack, <strong>Rails has quietly slipped from the spotlight over the past decade</strong>. While direct stats about framework usage can be hard to pin down, Ruby’s trajectory helps illustrate the shift. <a href="https://octoverse.github.com/">GitHub’s Octoverse</a> reports show Ruby falling from #5 (2014) to #10 (2022) in language rankings. The <a href="https://www.tiobe.com/tiobe-index/">TIOBE Index</a> recently pushed it to 24th, with its CEO bluntly suggesting Ruby is “likely to go out of fashion.” Ouch.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1229"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1227">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1228'
	>
	Community chatter reflects the mood. “Rails is just not what it once was,” <a href="https://www.reddit.com/r/rails/comments/17qvwsz/my_thoughts_on_the_rise_and_fall_of_ruby_on_rails/">wrote one long-time Redditor</a>. “The amount of jobs are way down and the pay is too.” Another chimed in: “It’s not COBOL — nothing that critical was written in it. Rails will eventually die.”</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1232"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1230">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1231'
	>
	But not everyone’s buying the obituary. Rails defenders argue it’s simply matured. It might no longer be trendy, but it’s still incredibly efficient. It does what it promises. It allows small teams to build and ship real products fast, without the overhead of piecing together half a dozen libraries. In an era where VC money is drying up and lean teams are the norm, that’s a value prop worth paying attention to.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1235"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1233">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1234'
	>
	We see this play out with companies we work with, many of which are organizations that run massive products on large Rails codebases. One client, with a market cap north of $2 billion, has definitely felt the pull to rebuild in something “modern.” But when it comes to cost and risk, the appeal fades fast. Some functionality is being moved to other stacks where it makes sense, but the core will likely stay on Rails for years. There’s simply no silver bullet waiting on the other side.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1236">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1237'
	>
	COBOL walked so Rails could… maintain</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1241"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1239">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1240'
	>
	To understand where Rails might be headed, it’s worth studying COBOL’s fate.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1244"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1242">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1243'
	>
	COBOL hasn’t been hot in decades, yet as of 2017, <strong>220 billion lines</strong> of it still powered key systems. Some estimates say <strong>43% of banking platforms</strong> and <strong>95% of ATM swipes</strong> involve COBOL code. Why? Because rewriting complex financial logic that’s business-critical (and often undocumented) is risky and expensive.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1247"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1245">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1246'
	>
	The kicker? Most COBOL developers are nearing retirement. In 2020, some U.S. states literally had to <a href="https://www.businessinsider.com/new-jersey-cobol-programmers-coronavirus-experts-mainframe-2020-4"><em>beg</em> for COBOL engineers</a> to fix outdated unemployment systems. And those engineers? They’re making bank.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1250"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1248">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1249'
	>
	COBOL is a classic case of technological inertia. As a consequence, it’s created a niche economy where a small number of specialists quietly hold the keys to critical systems. And they command serious salaries for doing so.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1253"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1251">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1252'
	>
	Rails is starting to look a lot like COBOL</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1256"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1254">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1255'
	>
	Just to be clear: Rails isn’t COBOL. But the trajectory? It rhymes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1259"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1257">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1258'
	>
	Many foundational platforms still run on Rails. Shopify’s massive monolith? Rails. GitHub? Rails. Basecamp? Rails, obviously. These companies aren’t rushing to rewrite their cores in Elixir or Go. Instead, they’re optimizing what works — and contributing back to the Rails ecosystem in the process.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1262"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1260">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1261'
	>
	Rails roles are also becoming more specialized. Junior opportunities are scarcer; most open positions are for mid-to-senior engineers with years of experience. But those who <em>are</em> experienced? They’re doing just fine. <a href="https://survey.stackoverflow.co/2023/">Stack Overflow’s 2023 survey</a> ranked Ruby as the <strong>4th highest-paying tech globally</strong>. Senior Rails engineers in the U.S. regularly clear six figures.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1265"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1263">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1264'
	>
	This is where the COBOL parallel kicks in: <strong>high compensation, low visibility, and a shrinking pipeline of new devs</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1268"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1266">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1267'
	>
	Less hype, more output</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1271"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1269">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1270'
	>
	Let’s kill the idea that Rails is frozen in time. It’s not.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1274"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1272">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1273'
	>
	Both Rails 7 and 8 are pushing forward with features that sidestep frontend fatigue. <a href="https://hotwired.dev/">Hotwire</a>, Turbo, and Stimulus let you build snappy UIs without reaching for React or Vue. Want realtime updates without drowning in JavaScript? Rails has that baked in.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1277"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1275">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1276'
	>
	On the backend, <strong>Ruby is still evolving</strong>. Turning 30 next year,<strong> it’s the same age as JavaScript, and it remains in active development</strong>. The Ruby 3&#215;3 initiative, launched back in 2015, <a href="https://www.heroku.com/blog/ruby-3-by-3/">committed</a> to making Ruby 3 three times faster than Ruby 2. That milestone was reached in 2020, and the momentum hasn’t stopped. Recent versions continue to bring performance gains through JIT compilers like YJIT and RJIT, as well as improvements to memory efficiency and startup times.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1280"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1278">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1279'
	>
	<strong>Rails 8 builds on this foundation</strong>. It is the version of Rails that remembers why people fell in love with it in the first place: fast setup, clear conventions, and a full-stack story that doesn’t require Kubernetes on day one. It even introduces <a href="https://github.com/rails/solid_queue">“Solid Queue”</a> for background jobs — no Redis, no drama.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1283"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1281">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1282'
	>
	And beyond the tooling, there’s still joy in writing Rails. As DHH recently pointed out in his post <a href="https://world.hey.com/dhh/coding-should-be-a-vibe-50908f49">Coding should be a vibe!</a>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1285"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-highlighted-text">
	<p	class='typography typography--size-36-text js-typography block-highlighted-text__typography'
	data-id='es-1284'
	>
	<em>Disgruntled programmers have finally realized that an escape from nasty syntax, boilerplate galore, and ecosystem hyper-churn is possible. That’s the appeal of AI: having it hide away all that unpleasantness. Only it’s like cleaning your room by stuffing the mess under the bed — it doesn’t make it go away!</em></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1288"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1286">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1287'
	>
	If developers are racing to offload coding to AI, maybe the problem lies in the stack itself.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1291"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1289">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1290'
	>
	Rails and Ruby offer a different path. It’s one that doesn’t require hiding the mess. Instead, they strip away unnecessary layers and let you <strong>build fast, clean, and human-readable code from day one</strong>. In that world, simplicity and elegance aren’t limitations. They’re advantages.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1294"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1292">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1293'
	>
	That’s also why we don’t skip upgrades. All of our active projects are already on Rails 7, and a couple have already adopted Rails 8. We use Hotwire and Turbo where it makes sense. Not because it’s fashionable, but because it solves real problems. Staying current gives us access to the latest features, but more importantly, it keeps our clients’ products secure.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1297"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1295">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1296'
	>
	Rails in a niche future</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1300"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1298">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1299'
	>
	So, is Rails becoming the boutique skillset for aging SaaS platforms?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1303"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1301">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1302'
	>
	Maybe. And that’s not a bad thing.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1306"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1304">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1305'
	>
	Rails still excels at building internal tools, MVPs, and stable CRUD-heavy platforms — especially for teams that value clarity over cleverness. Its “boring is good” philosophy is a feature, not a bug.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1309"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1307">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1308'
	>
	The community remains active, too. The main <a href="https://github.com/rails/rails">Rails repo</a> has seen over <strong>6,500 commits</strong> and <strong>1,500 issues closed</strong> in the past year. RailsConf draws a mix of grizzled veterans and Hotwire-happy newbies. Tools like <a href="https://docs.stimulusreflex.com/">StimulusReflex</a> and <a href="https://github.com/github/view_component">view components</a> show there’s still innovation happening, just at a more grounded pace.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1312"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1310">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1311'
	>
	The language and framework remain deeply aligned around developer happiness and productivity. Drastic deviations are unlikely to succeed, because <strong>what’s here doesn’t just work, it works very well</strong>. Newer languages and frameworks have their place, but Rails wasn’t built for the same constraints or audiences.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1313">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1314'
	>
	Rails isn’t a zombie. It’s simply not chasing trends anymore. It’s found its lane, and for the right teams, it’s still a dream to work with.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1318"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1316">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1317'
	>
	Not dead. Just different.</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1321"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1319">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1320'
	>
	Ruby on Rails isn’t dying. It’s aging into its next role. Think less rockstar, more session musician. Still sharp, still useful, still quietly keeping the show running.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1324"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1322">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1323'
	>
	It might not be the framework new grads rush to learn, and it might not top the charts anymore. But for many companies, Rails is still a pragmatic choice. It delivers. It scales (when engineered well). And in a tech world increasingly obsessed with complexity, Rails dares to stay simple.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1327"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1325">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1326'
	>
	Smart engineering teams are well-aware: smart, stable software never goes out of style. So maybe, in 10 years, we’ll talk about Rails the same way we talk about COBOL: a relic, yes — but a reliable one. And in the end, reliability is underrated.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1330"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1328">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1329'
	>
	At Infinum, <strong>we’re here for both sides of the Rails story</strong>. Both if you’re looking to extend the life of a legacy system, or weighing Rails against shinier options for a new build. Check out our <a href="https://infinum.com/rails-support-maintenance/"><strong>Rails Maintenance &amp; Support services</strong></a> if your app needs some love (or a performance tune-up), or reach out if you’re on the fence about which tech stack fits your product best.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/is-ruby-on-rails-becoming-the-new-cobol/">Is Ruby on Rails Becoming the New COBOL?</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19265085https://infinum.com/uploads/2025/04/Playwright-blog-hero.webp</url>
				</image>
				<title>Automation Made Simple: Accessibility Testing with Playwright</title>
				<link>https://infinum.com/blog/accessibility-testing-automation-playwright/</link>
				<pubDate>Thu, 03 Apr 2025 11:43:46 +0000</pubDate>
				<dc:creator>Dino Vinković</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19265085</guid>
				<description>
					<![CDATA[<p>Learn how to speed up your accessibility checks using Playwright and axe-core, and simplify the path to building more inclusive digital products.</p>
<p>The post <a href="https://infinum.com/blog/accessibility-testing-automation-playwright/">Automation Made Simple: Accessibility Testing with Playwright</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-1460"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1333">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1336"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1334">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-1335'
	>
	<strong>With automation tools like Playwright, testing web accessibility doesn’t have to be tedious or time-consuming. Learn how to speed up your accessibility checks using Playwright and axe-core, and simplify the path to building more inclusive digital products.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1339"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1337">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1338'
	>
	Ensuring your web page is accessible to all users is becoming increasingly important for businesses. With <a href="https://infinum.com/blog/european-accessibility-act/" target="_blank" rel="noreferrer noopener">regulatory pressures mounting</a> and public awareness rising, brands and companies are looking to optimize their digital products to meet accessibility standards.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1342"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1340">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1341'
	>
	However, <a href="https://infinum.com/blog/how-to-get-started-with-accessibility-testing/" target="_blank" rel="noreferrer noopener">testing a web page for accessibility</a> is a nuanced task, and certain aspects of it can be particularly time-consuming. Fortunately, there are a number of tools available to help testers check web accessibility thoroughly and efficiently, especially by leveraging test automation.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1345"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1343">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1344'
	>
	Not every team has the resources or bandwidth to build custom tools, but existing solutions can already achieve a great deal. In this article, we’ll explain how to conduct accessibility testing using Playwright, a very popular tool in the testing community. With just a few simple adjustments, Playwright can significantly speed up and enhance the efficiency of your testing process.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1348"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1346">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1347'
	>
	<strong>Why digital accessibility is important</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1351"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1349">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1350'
	>
	A significant portion of the population faces challenges when accessing digital resources due to physical, cognitive, and sensory impairments. According to the World Health Organization, <a href="https://www.who.int/news-room/fact-sheets/detail/disability-and-health" target="_blank" rel="noreferrer noopener">approximately 16% of the global population experiences significant disabilities</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1354"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1352">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1353'
	>
	If your app or website isn’t built with accessibility in mind, you risk excluding a considerable number of users – not only those with permanent disabilities but also individuals experiencing temporary or situational impairments, such as a broken arm or navigating a digital product in a noisy environment. Accessibility standards ultimately improve the user experience for everyone.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1357"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1355">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1356'
	>
	Beyond ethical considerations, accessibility is increasingly becoming a legal necessity. In the United States, the <a href="https://www.ada.gov/" target="_blank" rel="noreferrer noopener">Americans with Disabilities Act</a> mandates that public accommodations, including websites, must be accessible to individuals with disabilities. Similarly, the European Union’s <a href="https://commission.europa.eu/strategy-and-policy/policies/justice-and-fundamental-rights/disability/union-equality-strategy-rights-persons-disabilities-2021-2030/european-accessibility-act_en" target="_blank" rel="noreferrer noopener">European Accessibility Act</a> and the <a href="https://digital-strategy.ec.europa.eu/en/policies/web-accessibility-directive-standards-and-harmonisation" target="_blank" rel="noreferrer noopener">Web Accessibility Directive</a> establish clear guidelines for digital accessibility. Non-compliance can lead to significant legal consequences, including lawsuits, fines, and reputational harm.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1360"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1358">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1359'
	>
	<strong>What is accessibility testing?</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1363"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1361">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1362'
	>
	Accessibility testing is the process of identifying barriers that may prevent users from fully interacting with a website or service. It ensures that people with disabilities can access and navigate the content just as easily as anyone else.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1366"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1364">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1365'
	>
	The testing is usually conducted through a combination of automated and manual accessibility checks. It evaluates several aspects, including visual design, interactive elements, content structure, navigation, and multimedia components.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1369"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1367">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1368'
	>
	Can accessibility testing be automated?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1372"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1370">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1371'
	>
	Accessibility testing can be automated to a certain extent. Automation tools can help us identify many common accessibility issues and provide reports that highlight areas needing improvement. These tools can check for issues like missing alt text, poor color contrast, improper heading structures, and missing ARIA attributes – areas frequently overlooked during development.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1375"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1373">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1374'
	>
	However, automated tools are limited to verifying basic accessibility compliance and cannot evaluate how intuitive or user-friendly an interface is. Human testing remains vital for uncovering issues such as confusing navigation, unintuitive layouts, or frustrating interactions, which are all essential if we want to ensure a truly inclusive user experience.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1378"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1376">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1377'
	>
	Automating accessibility testing with Plawright and axe-core</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1381"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1379">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1380'
	>
	<a href="https://playwright.dev/" target="_blank" rel="noreferrer noopener">Playwright</a> is an excellent starting point for teams interested in accessibility test automation. It is a widely used, open-source framework known for its ease of setup and strong community support. More importantly, it offers integration with axe-core, a powerful accessibility testing library created by Deque Systems. <a href="https://github.com/dequelabs/axe-core-npm" target="_blank" rel="noreferrer noopener">Axe-core</a> helps testers efficiently detect violations of accessibility standards, such as the Web Content Accessibility Guidelines (WCAG), and provides insights on fixing any issues found.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1384"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1382">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1383'
	>
	Playwright and axe-core are a powerful combo – one that helps testers streamline accessibility checks, improving both efficiency and accuracy in their testing processes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1387"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1385">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1386'
	>
	<strong>Initial setup</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1390"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1388">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1389'
	>
	We’ll start by installing Playwright using <code>npm</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1392"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">npm</span><span class="token"> </span><span class="token" style="color: #005cc5;">init</span><span class="token"> </span><span class="token" style="color: #005cc5;">playwright</span><span class="token" style="color: #d73a49;">@</span><span class="token" style="color: #005cc5;">latest</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1395"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1393">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1394'
	>
	You’ll be prompted to answer a few setup questions – feel free to go with the default options. TypeScript should be selected by default, but double-check that it is.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1398"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1396">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1397'
	>
	For full installation details, check the <a href="https://playwright.dev/docs/intro" target="_blank" rel="noreferrer noopener">official Playwright documentation</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1401"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1399">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1400'
	>
	Next, add the additional packages needed for this implementation:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1403"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">npm</span><span class="token"> </span><span class="token" style="color: #005cc5;">install</span><span class="token"> </span><span class="token" style="color: #d73a49;">@</span><span class="token" style="color: #005cc5;">axe</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">core</span><span class="token" style="color: #d73a49;">/</span><span class="token" style="color: #005cc5;">playwright</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">npm</span><span class="token"> </span><span class="token" style="color: #005cc5;">install</span><span class="token"> </span><span class="token" style="color: #005cc5;">axe</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">html</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">reporter</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1406"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1404">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1405'
	>
	Then, import the necessary modules in your test file:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1408"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">test</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">expect</span><span class="token"> </span><span class="token">}</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">@playwright/test</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token" style="color: #005cc5;">AxeBuilder</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">@axe-core/playwright</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">createHtmlReport</span><span class="token"> </span><span class="token">}</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">axe-html-reporter</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1411"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1409">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1410'
	>
	<strong>Page inspection</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1414"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1412">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1413'
	>
	Now, let&#8217;s walk through a practical example using <a href="https://todomvc.com/" target="_blank" rel="noreferrer noopener">todoMVC</a>. To inspect a page for accessibility issues, we’ll use<strong> </strong><code>AxeBuilder</code> from the <code>axe-core/playwright package</code>.  The command <code>new AxeBuilder({ page }).analyze()</code> tells Axe to scan the current page and identify any violations according to established standards, and the results are stored in the <code>accessibilityScanResults</code> variable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1416"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">accessibilityScanResults</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">await</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #005cc5;">AxeBuilder</span><span class="token">(</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">page</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">analyze</span><span class="token">(</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1419"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1417">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1418'
	>
	To focus the analysis on specific standards, you can refine the accessibility scan by using the <code>withTags()</code> method. For example, if you’re targeting the most common WCAG compliance levels (WCAG 2.0 and WCAG 2.1, levels A and AA), you can do so as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1421"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">accessibilityScanResults</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">await</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #005cc5;">AxeBuilder</span><span class="token">(</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">page</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">       </span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">withTags</span><span class="token">([&#039;</span><span class="token" style="color: #6f42c1;">wcag</span><span class="token" style="color: #032f62;">2a</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">wcag2aa</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">wcag21a</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">wcag21aa</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">       </span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">analyze</span><span class="token">();
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1424"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1422">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1423'
	>
	<strong>Assertion</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1427"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1425">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1426'
	>
	After performing the scan, we need to verify whether any accessibility violations have occurred. You can achieve this by asserting that the violations array within the results is empty. If any violations are found, your test will fail, prompting you to address the identified issues:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1429"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">expect</span><span class="token">(</span><span class="token" style="color: #005cc5;">accessibilityScanResults</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #005cc5;">violations</span><span class="token">)</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">toEqual</span><span class="token">(</span><span class="token">[</span><span class="token">]</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1432"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1430">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1431'
	>
	<strong>Creating the report</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1435"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1433">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1434'
	>
	To generate a readable summary of the accessibility scan, we’ll use the <code>createHtmlReport</code><strong> </strong>function from<strong> </strong>the<strong> </strong><code>axe-html-reporter</code> package. This function takes in the scan results  we previously stored in <code>accessibilityScanResults</code>. We can also use options to configure the report name and output directory.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1437"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-javascript github-light" data-language="javascript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportHTML</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #6f42c1;">createHtmlReport</span><span class="token">(</span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">results</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #24292e;">accessibilityScanResults</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">options</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">outputDir</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #24292e;">reportDir</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">reportFileName</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #24292e;">reportName</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1440"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1438">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1439'
	>
	Note that <code>createHtmlReport</code> returns an HTML string – it doesn’t create a file by itself. To write the report to disk, we’ll use Node’s <code>fs</code> module:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1442"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #d73a49;">!</span><span class="token" style="color: #005cc5;">fs</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">existsSync</span><span class="token">(</span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportDir</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportName</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">`</span><span class="token">)</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">       fs</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">mkdirSync</span><span class="token">(`${</span><span class="token" style="color: #6f42c1;">rep</span><span class="token" style="color: #24292e;">ortD</span><span class="token" style="color: #032f62;">ir}</span><span class="token" style="color: #24292e;">${reportNa</span><span class="token" style="color: #032f62;">me}</span><span class="token" style="color: #032f62;">`</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">recursive</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">true</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">     </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">     fs</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">writeFileSync</span><span class="token">(`${</span><span class="token" style="color: #6f42c1;">r</span><span class="token" style="color: #24292e;">eportD</span><span class="token" style="color: #032f62;">ir}</span><span class="token" style="color: #24292e;">${reportNa</span><span class="token" style="color: #032f62;">me}</span><span class="token" style="color: #032f62;">`</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportHTML</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1445"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1443">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1444'
	>
	<strong>Parametrizing the test</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1448"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1446">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1447'
	>
	Testing a single page is a good start, but broader coverage requires more. Let’s modify our test to run against multiple pages by creating an array of objects containing <code>URL/name</code> pairs. The <code>URL</code> field tells Playwright which page to check, and the <code>name</code> field isn’t required, but helps us generate more descriptive report names:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1450"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">urlsToCheck</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">[</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">url</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">https://todomvc.com/examples/react/dist/</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">name</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">reactPage</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">url</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">https://todomvc.com/examples/angular/dist/browser/#/all</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">name</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">angularPage</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">url</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">https://todomvc.com/examples/javascript-es6/dist/</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">name</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">jsPage</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">]</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1453"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1451">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1452'
	>
	Next, we’ll loop through each URL in our test using <code>forEach</code>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1455"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">test</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">describe</span><span class="token">(</span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">Accessibility</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token"> </span><span class="token">(</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">=&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;"> urlsToCheck</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">forEach</span><span class="token">(</span><span class="token">(</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">url</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">name</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">=&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">   test</span><span class="token">(`</span><span class="token" style="color: #6f42c1;">s</span><span class="token" style="color: #032f62;">hould check: </span><span class="token" style="color: #24292e;">${u</span><span class="token" style="color: #032f62;">rl}</span><span class="token" style="color: #032f62;">`</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #6f42c1;">async</span><span class="token"> ({</span><span class="token"> </span><span class="token" style="color: #005cc5;">page</span><span class="token"> </span><span class="token">}</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">testInfo</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">=&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">…</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1458"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1456">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1457'
	>
	This setup generates a separate, clearly labeled report for each tested page.</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-1463"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-1461"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-1462">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2025/04/a11y-playwright-in-article-1-1400x1246.webp				media='(max-width: 699px)'
				type=image/webp								height="1246"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2025/04/a11y-playwright-in-article-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1280"
															width="1438"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-1486"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1467">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1466"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1464">
	</div>	</div>
</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1470"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1468">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1469'
	>
	The <strong>full example</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1473"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1471">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1472'
	>
	Here&#8217;s how the complete test script comes together. This is a simple example that shows how easy it is to get started with accessibility test automation using Playwright and axe-core:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1475"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">test</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">expect</span><span class="token"> </span><span class="token">}</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">@playwright/test</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token" style="color: #005cc5;">AxeBuilder</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">@axe-core/playwright</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">createHtmlReport</span><span class="token"> </span><span class="token">}</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">axe-html-reporter</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">import</span><span class="token"> </span><span class="token" style="color: #005cc5;">fs</span><span class="token"> </span><span class="token" style="color: #005cc5;">from</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">fs</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportDir</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">reports/a11y/</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">urlsToCheck</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">[</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">url</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">https://todomvc.com/examples/react/dist/</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">name</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">reactPage</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">url</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">https://todomvc.com/examples/angular/dist/browser/#/all</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">name</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">angularPage</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">url</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">https://todomvc.com/examples/javascript-es6/dist/</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">name</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">jsPage</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">]</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">test</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">describe</span><span class="token">(</span><span class="token" style="color: #032f62;">&#039;</span><span class="token" style="color: #032f62;">Accessibility</span><span class="token" style="color: #032f62;">&#039;</span><span class="token">,</span><span class="token"> </span><span class="token">(</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">=&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #005cc5;">urlsToCheck</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">forEach</span><span class="token">(</span><span class="token">(</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">url</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">name</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">=&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6f42c1;">test</span><span class="token">(</span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">should check: </span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">url</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">`</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #6f42c1;">async</span><span class="token"> </span><span class="token">(</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">page</span><span class="token"> </span><span class="token">}</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">testInfo</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">=&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportName</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">name</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">.html</span><span class="token" style="color: #032f62;">`</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #005cc5;">await</span><span class="token"> </span><span class="token" style="color: #005cc5;">page</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">goto</span><span class="token">(</span><span class="token" style="color: #005cc5;">url</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Scan the page and save results to accessibilityScanResults</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">accessibilityScanResults</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">await</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #005cc5;">AxeBuilder</span><span class="token">(</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">page</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">analyze</span><span class="token">(</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Create HTML report</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportHTML</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #6f42c1;">createHtmlReport</span><span class="token">(</span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #6f42c1;">results</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">accessibilityScanResults</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #6f42c1;">options</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #6f42c1;">outputDir</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportDir</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #6f42c1;">reportFileName</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportName</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Save HTML report to a file</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #d73a49;">!</span><span class="token" style="color: #005cc5;">fs</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">existsSync</span><span class="token">(</span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportDir</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportName</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">`</span><span class="token">)</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #005cc5;">fs</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">mkdirSync</span><span class="token">(</span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportDir</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportName</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">`</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #005cc5;">recursive</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">true</span><span class="token"> </span><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #005cc5;">fs</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">writeFileSync</span><span class="token">(</span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportDir</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">${</span><span class="token" style="color: #24292e;">reportName</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">`</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">reportHTML</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Assert no violations detected</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #6f42c1;">expect</span><span class="token">(</span><span class="token" style="color: #005cc5;">accessibilityScanResults</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #005cc5;">violations</span><span class="token">)</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #6f42c1;">toEqual</span><span class="token">(</span><span class="token">[</span><span class="token">]</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1478"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1476">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-1477'
	>
	<strong>Report</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1481"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1479">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1480'
	>
	The reports generated by axe-core are clear, detailed, and practical. They highlight each accessibility violation, categorize its severity, and point to the relevant WCAG guideline. For every issue, you’ll see the specific DOM element affected and get actionable suggestions on how to fix it.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1484"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1482">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1483'
	>
	What’s especially helpful is that each issue comes with documentation links, allowing testers and developers to learn more about the problem and why it matters – making it easier to address issues effectively and build more inclusive products.</p></div>	</div>
</div>
</div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-1489"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-1487"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-1488">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2025/04/a11y-playwright-in-article-2-1400x904.webp				media='(max-width: 699px)'
				type=image/webp								height="904"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2025/04/a11y-playwright-in-article-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="1280"
															width="1982"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>		</div>
	</div>

<div
	class="wrapper"
	data-id="es-1507"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1493">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1492"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1490">
	</div>	</div>
</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1496"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1494">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1495'
	>
	<strong>Make accessibility testing work for you</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1499"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1497">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1498'
	>
	Digital accessibility is no longer a nice-to-have – it’s becoming increasingly relevant for businesses looking to provide equal access for all users and reduce legal and reputational risks. However, evaluating accessibility manually can be time-consuming and prone to human error. Test automation can be a great asset for testers, and tools like Playwright and axe-core make it easy to catch many common accessibility issues early in the development process. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1502"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1500">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1501'
	>
	As our example shows, setting up automated tests doesn’t require complex custom solutions – just a few lines of code and the right tools. Still, we need to bear in mind that automation isn’t a silver bullet. Automated tests are powerful allies, not replacements for human judgment. Experienced testers use these tools to boost efficiency and consistency, while still applying manual testing to assess usability, context, and the overall user experience.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1505"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1503">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1504'
	>
	Ultimately, the best approach combines speed with empathy – automating what you can and thoughtfully testing what you can’t.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/accessibility-testing-automation-playwright/">Automation Made Simple: Accessibility Testing with Playwright</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19264889https://infinum.com/uploads/2025/03/Swift-Sanitizer-min.webp</url>
				</image>
				<title>Time to Get Real – Introducing RealtimeSanitizer for Swift</title>
				<link>https://infinum.com/blog/realtimesanitizer-swift/</link>
				<pubDate>Wed, 26 Mar 2025 12:21:43 +0000</pubDate>
				<dc:creator>Josip Ćavar</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19264889</guid>
				<description>
					<![CDATA[<p>Meet RTSanStandaloneSwift, our Swift wrapper around RealtimeSanitizer, helping you write predictable and safe real-time code.</p>
<p>The post <a href="https://infinum.com/blog/realtimesanitizer-swift/">Time to Get Real – Introducing RealtimeSanitizer for Swift</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-1629"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1508">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1511"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1509">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-1510'
	>
	<strong>Swift is modern, powerful, and versatile – but real-time coding can get tricky. Meet RTSanStandaloneSwift, our new Swift wrapper around LLVM&#8217;s RealtimeSanitizer, designed to help you write safe and effective</strong> <strong>real-time code.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1514"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1512">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1513'
	>
	Developing robust real-time systems brings a unique set of challenges. Real-time code must not only be logically correct but also execute within strict time constraints. Failing to meet these deadlines can lead to system failures, which means that thorough debugging and validation of real-time safety are absolutely essential. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1517"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1515">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1516'
	>
	To simplify this intricate process, LLVM 20 introduces <a href="https://clang.llvm.org/docs/RealtimeSanitizer.html" target="_blank" rel="noreferrer noopener">RealtimeSanitizer</a> – a runtime analysis tool designed to detect operations that violate real-time constraints. While RealtimeSanitizer is initially available in the Clang compiler, its foundations are built within LLVM, allowing for broader language adoption. This has already been demonstrated with the <a href="https://steck.tech/posts/rtsan-in-rust/" target="_blank" rel="noreferrer noopener">Rust wrapper</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1520"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1518">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1519'
	>
	Over the past several months, we’ve collaborated with Chris Apple and David Trevelyan, creators of RealtimeSanitizer, to bring this powerful capability to Swift. Today, we’re excited to introduce <a href="https://github.com/realtime-sanitizer/RTSanStandaloneSwift" target="_blank" rel="noreferrer noopener">RTSanStandaloneSwift</a> – a Swift wrapper around RealtimeSanitizer that will enable Swift developers to build and maintain real-time applications more easily.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1523"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1521">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1522'
	>
	Real-time programming in Swift</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1526"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1524">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1525'
	>
	C and C++ have long dominated real-time development due to their predictable performance and low-level control.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1529"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1527">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1528'
	>
	Swift, on the other hand, is a modern, fast, and memory-safe language that is interoperable with C++ and has cross-platform support, making it an attractive option for a wide range of applications.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1534"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-1530">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-1531'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-1532'
	>
	Swift’s project goal is to create the best available language for uses ranging from systems programming to mobile and desktop apps, scaling up to highly distributed cloud services.</p>
		<div class="blockquote__caption-wrap">
			<div	class='typography typography--size-12-text-roman js-typography blockquote__caption'
	data-id='es-1533'
	>
	<a href="http://Swift.org">SWIFT.ORG</a></div>		</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1537"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1535">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1536'
	>
	While Swift has already demonstrated its <a href="https://fosdem.org/2025/schedule/event/fosdem-2025-5284-building-a-ferrofluidic-music-visualizer-with-embedded-swift/" target="_blank" rel="noreferrer noopener">capability as a real-time programming language</a>, its high-level nature can make it challenging to reason about strict execution time requirements.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1540"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1538">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1539'
	>
	Let’s examine a simple Swift implementation of an audio processor:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1542"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class AudioProcessor</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">var</span><span class="token"> gain </span><span class="token" style="color: #d73a49;">= 1
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">func process</span><span class="token">(</span><span class="token">buffer</span><span class="token">: </span><span class="token" style="color: #d73a49;">inout</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">Float</span><span class="token">]</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">for</span><span class="token"> i </span><span class="token" style="color: #d73a49;">in</span><span class="token"> 0.</span><span class="token" style="color: #d73a49;">.&lt;buffer.c</span><span class="token" style="color: #005cc5;">ount</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            buffer</span><span class="token">[</span><span class="token">i</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">= buffer[i] *</span><span class="token" style="color: #d73a49;"> gain
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1545"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1543">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1544'
	>
	Although this example resembles a straightforward C-style loop, it contains several potential pitfalls for real-time performance:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1548"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1546">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1547'
	>
	<li>Exclusivity checking – which may allocate memory</li><li>Protocol lookup and metadata instantiation  – which may allocate memory or introduce locks</li><li>Copy-on-write behaviour on the array – which may allocate memory</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1551"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1549">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1550'
	>
	Having a tool that can help us detect these issues would be invaluable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1554"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1552">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1553'
	>
	How RealtimeSanitizer works</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1557"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1555">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1556'
	>
	Similar to AddressSanitizer, RealtimeSanitizer works by intercepting “interesting” functions – in this context, those that could violate realtime-safety guarantees. Typically, these functions involve locks, memory allocation or I/O operations.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1560"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1558">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1559'
	>
	For a full list of intercepted functions, check out the <a href="https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp" target="_blank" rel="noreferrer noopener">implementation</a> details.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1563"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1561">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1562'
	>
	In C++ (Clang), real-time sanitizer is <strong>activated</strong> by annotating a function with the <code>[[clang:nonblocking]]</code> attribute. When such a function invokes a real-time unsafe operation, the sanitizer aborts the process and provides a stack trace for debugging purposes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1566"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1564">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1565'
	>
	RealtimeSanitizer also includes <a href="https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/rtsan/rtsan.h" target="_blank" rel="noreferrer noopener">a suite of C functions</a> that give developers fine-grained control over its behaviour.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1569"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1567">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1568'
	>
	RealtimeSanitizer in Swift</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1572"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1570">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1571'
	>
	Leveraging Swift’s interoperability with C, we can invoke RealtimeSanitizer’s C bindings and create a more convenient Swift API.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1575"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1573">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1574'
	>
	RTSanStandaloneSwift is a lightweight implementation that introduces a user-friendly Swift macro for annotating functions that are subject to real-time constraints.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1578"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1576">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1577'
	>
	Similar to the <code>[[clang:nonblocking]]</code><em> </em>attribute in C++, RTSanStandaloneSwift provides the <code>@NonBlocking</code><em> </em>macro in Swift.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1581"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1579">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1580'
	>
	For example, we can annotate our earlier <code>process</code> function like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1583"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">@NonBlocking</span><span class="token">
</span></span><span class="line"><span class="token">func process</span><span class="token">(</span><span class="token">buffer</span><span class="token">: </span><span class="token" style="color: #d73a49;">inout</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #005cc5;">Float</span><span class="token">]</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">for</span><span class="token"> i i</span><span class="token" style="color: #d73a49;">n</span><span class="token"> </span><span class="token" style="color: #005cc5;">0</span><span class="token" style="color: #d73a49;">..&lt;buff</span><span class="token">er.</span><span class="token" style="color: #005cc5;">count</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        buffer</span><span class="token">[</span><span class="token">i</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">= buffer[</span><span class="token">i</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #d73a49;">* gain
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1586"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1584">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1585'
	>
	Now, when we run this code, RealtimeSanitizer will automatically detect and report any real-time violations:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1588"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">==</span><span class="token" style="color: #005cc5;">11917</span><span class="token" style="color: #d73a49;">==</span><span class="token" style="color: #005cc5;">ERROR</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">RealtimeSanitizer</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">unsafe</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">library</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">call</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">Intercepted</span><span class="token"> </span><span class="token" style="color: #005cc5;">call</span><span class="token"> </span><span class="token" style="color: #005cc5;">to</span><span class="token"> </span><span class="token" style="color: #d73a49;">real</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">time</span><span class="token"> </span><span class="token" style="color: #005cc5;">unsafe</span><span class="token"> </span><span class="token" style="color: #d73a49;">function</span><span class="token"> </span><span class="token" style="color: #032f62;">`</span><span class="token" style="color: #032f62;">os_unfair_lock_lock</span><span class="token" style="color: #032f62;">`</span><span class="token"> </span><span class="token" style="color: #005cc5;">in</span><span class="token"> </span><span class="token" style="color: #d73a49;">real</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">time</span><span class="token"> </span><span class="token" style="color: #005cc5;">context</span><span class="token" style="color: #d73a49;">!</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">0 in os_unfair_lock_lock rtsan_interceptors_posix.cpp:592</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">1 in _swift_allocObject_+0x1b4 (libswiftCore.dylib:arm64)</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">2 in _ArrayBuffer._consumeAndCreateNew(bufferIsUnique:minimumCapacity:)</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">3 0x00010061f5a4 in AudioProcessor_main main.swift:26</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">SUMMARY</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">RealtimeSanitizer</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">unsafe</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">library</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #6f42c1;">call</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #005cc5;">libswiftCore</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #005cc5;">dylib</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #005cc5;">in</span><span class="token"> </span><span class="token" style="color: #005cc5;">_swift_allocObject</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1591"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1589">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1590'
	>
	In this particular example, RealtimeSanitizer detected a lock within the Swift runtime triggered by the copy-on-write behavior during array mutation.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1594"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1592">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1593'
	>
	RTSanStandaloneSwift roadmap</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1597"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1595">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1596'
	>
	We consider the current version of RTSanStandaloneSwift a <strong>transitional solution, </strong>and plan further improvements in the next stages:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1600"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1598">
	<h3	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1599'
	>
	Stage 1</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1603"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1601">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1602'
	>
	Currently, RTSanStandaloneSwift ships with a prebuilt version of the RealtimeSanitizer dynamic library. While this approach is functional, it is not ideal in the long term.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1606"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1604">
	<h3	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1605'
	>
	Stage 2</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1609"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1607">
	<p	class='typography typography--size-20-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1608'
	>
	<a href="https://github.com/llvm/llvm-project/releases/tag/llvmorg-20.1.0" target="_blank" rel="noreferrer noopener">LLVM 20 is officially out</a>, so when the first Swift nightly toolchains targeting LLVM 20 become available, we plan to phase out the prebuilt versions of the RealtimeSanitizer dynamic library. At that point, RTSanStandaloneSwift will rely entirely on the RealtimeSanitizer functionality provided directly in the toolchain.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1612"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1610">
	<h2	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1611'
	>
	Stage 3</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1615"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1613">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1614'
	>
	Ultimately, our goal is to make a pitch for adding the attributes and the sanitizer as first-class features natively integrated into Swift.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1618"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1616">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1617'
	>
	Get involved and try it out</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1621"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1619">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1620'
	>
	RTSanStandaloneSwift marks a significant milestone for real-time programming in Swift, enabling Swift developers to more easily write predictable and safe real-time code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1624"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1622">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1623'
	>
	We’d love you to try it out, share your feedback and contribute to its ongoing development.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1627"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1625">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1626'
	>
	<li><strong>Github</strong>: <a href="https://github.com/realtime-sanitizer/RTSanStandaloneSwift">RTSanStandaloneSwift Repository</a> </li><li><strong>Official documentation</strong>: <a href="https://clang.llvm.org/docs/RealtimeSanitizer.html">RealtimeSanitizer Docs</a></li><li><strong>Swift Package Index</strong>: <a href="https://swiftpackageindex.com/realtime-sanitizer/RTSanStandaloneSwift">RTSanStandaloneSwift Package</a></li><li><strong>Discord</strong>: <a href="https://discord.gg/DZqjbmSZzZ">RealtimeSanitizer (RTSan)</a></li><li><strong>Email</strong>: <a href="mailto:realtime.sanitizer@gmail.com" target="_blank" rel="noreferrer noopener">realtime.sanitizer@gmail.com</a></li><li><strong>Swift Forums</strong>: <a href="https://forums.swift.org/t/introducing-realtimesanitizer-for-swift" target="_blank" rel="noreferrer noopener">RealtimeSanitizer for Swift thread</a><br />
</li></ul></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/realtimesanitizer-swift/">Time to Get Real – Introducing RealtimeSanitizer for Swift</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>19264334https://infinum.com/uploads/2025/02/Blog-hero-kotlin-ultiplatform-img-min.webp</url>
				</image>
				<title>Kotlin Multiplatform – Bridging Compose &#038; iOS UI Frameworks</title>
				<link>https://infinum.com/blog/kotlin-multiplatform-swiftui/</link>
				<pubDate>Wed, 26 Feb 2025 19:12:50 +0000</pubDate>
				<dc:creator>Giorgio Provenzale</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=19264334</guid>
				<description>
					<![CDATA[<p>Exploring practical approaches to integrating Kotlin Compose with iOS frameworks like UIKit and SwiftUI.</p>
<p>The post <a href="https://infinum.com/blog/kotlin-multiplatform-swiftui/">Kotlin Multiplatform – Bridging Compose &amp; iOS UI Frameworks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-1761"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-1630">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1633"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1631">
	<p	class='typography typography--size-36-text js-typography block-paragraph__paragraph'
	data-id='es-1632'
	>
	<strong>Kotlin Multiplatform lets you share core business logic while still taking full advantage of native UI components. We explore practical approaches to integrating Kotlin Compose with iOS frameworks like UIKit and SwiftUI.</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1636"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1634">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1635'
	>
	Mobile developers often face the challenge of balancing consistent business logic with the unique demands of each platform’s user interface. Kotlin Multiplatform (KMP) is a great choice for tackling this, allowing developers to write shared business logic while retaining platform-specific flexibility. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1639"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1637">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1638'
	>
	When it comes to integrating UI frameworks like Compose with native iOS components (e.g., SwiftUI or UIKit), KMP offers multiple approaches tailored to various use cases. This article discusses the core <code>expect/actual</code> pattern – the foundation of KMP&#8217;s platform-specific customizations – and presents two additional strategies: using <code>UIViewControllerRepresentable</code> to integrate SwiftUI and directly accessing iOS native APIs through <code>platform.UIKit</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1642"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1640">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1641'
	>
	<strong>The foundation: the <code>expect/actual</code> pattern in KMP</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1645"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1643">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1644'
	>
	The <code>expect/actual</code> pattern is the cornerstone of Kotlin Multiplatform development. It enables developers to define shared abstractions (<code>expect</code>) and provide platform-specific implementations (<code>actual</code>). This approach is particularly useful when you want to share as much logic as possible while accommodating platform-specific details, including UI components.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1648"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1646">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1647'
	>
	Example:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1651"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1649">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1650'
	>
	<strong>Shared code: <code>expect</code> declaration</strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1653"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">expect </span><span class="token">fun showPlatformDialog</span><span class="token">(message</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">)
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1656"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1654">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1655'
	>
	<strong><strong>iOS implementation</strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1658"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">actual </span><span class="token">fun showPlatformDialog</span><span class="token">(message</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">) {
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">alert </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">UIAlertController</span><span class="token">(
</span></span><span class="line"><span class="token">        title </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">iOS Dialog</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,
</span></span><span class="line"><span class="token">        message </span><span class="token" style="color: #d73a49;">=</span><span class="token"> message,
</span></span><span class="line"><span class="token">        preferredStyle </span><span class="token" style="color: #d73a49;">=</span><span class="token"> UIAlertControllerStyleAlert
</span></span><span class="line"><span class="token">    )
</span></span><span class="line"><span class="token">    alert</span><span class="token">.addAction</span><span class="token">(
</span></span><span class="line"><span class="token">        UIAlertAction</span><span class="token">.actionWithTitle</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">OK</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, UIAlertActionStyleDefault, </span><span class="token" style="color: #005cc5;">null</span><span class="token">)
</span></span><span class="line"><span class="token">    )
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">rootViewController </span><span class="token" style="color: #d73a49;">=</span><span class="token"> UIApplication.sharedApplication.keyWindow?.rootViewController
</span></span><span class="line"><span class="token">    rootViewController</span><span class="token">?.presentViewController</span><span class="token">(alert, animated </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">true</span><span class="token">, completion </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">null</span><span class="token">)
</span></span><span class="line"><span class="token">}
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1661"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1659">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1660'
	>
	<strong><strong>Android implementation</strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1663"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">actual </span><span class="token">fun showPlatformDialog</span><span class="token">(message</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">) {
</span></span><span class="line"><span class="token">    AlertDialog</span><span class="token">.Builder</span><span class="token">(context)
</span></span><span class="line"><span class="token">        </span><span class="token">.setMessage</span><span class="token">(message)
</span></span><span class="line"><span class="token">        </span><span class="token">.setPositiveButton</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">OK</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, </span><span class="token" style="color: #005cc5;">null</span><span class="token">)
</span></span><span class="line"><span class="token">        </span><span class="token">.show</span><span class="token">()
</span></span><span class="line"><span class="token">}
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1666"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1664">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1665'
	>
	This pattern ensures:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1669"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1667">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1668'
	>
	<li><strong>Platform independence:</strong> Core logic remains in the shared module.</li><li><strong>Flexibility:</strong> Platform-specific UI implementations can vary greatly.</li><li><strong>Extensibility:</strong> New platforms can be added with minimal disruption.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1672"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1670">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1671'
	>
	While powerful, this pattern primarily handles business logic or modular UI components. More specialized use cases, such as embedding SwiftUI views or accessing native APIs directly, will require additional techniques.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1675"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1673">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1674'
	>
	<strong>1. Direct access to iOS APIs via <code>platform.UIKit</code></strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1678"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1676">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1677'
	>
	For developers requiring granular control over native iOS functionalities, directly accessing APIs via <code>platform.UIKit</code> is a powerful alternative. This method uses UIKit directly, allowing you to manipulate UIKit components and system APIs directly in Kotlin.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1681"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1679">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1680'
	>
	Example:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1684"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1682">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1683'
	>
	Again, we’ll start with the first dialog example.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1687"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1685">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1686'
	>
	<strong><strong>Shared code: <code>expect</code> declaration</strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1689"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">expect </span><span class="token">fun showPlatformDialog</span><span class="token">(message</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">)
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1692"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1690">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1691'
	>
	<strong><strong><strong>iOS implementation: creating and displaying a native alert dialog</strong></strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1694"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">import</span><span class="token"> </span><span class="token" style="color: #6f42c1;">platform.UIKit.</span><span class="token" style="color: #005cc5;">*</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">actual </span><span class="token">fun showPlatformDialog</span><span class="token">() {
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">alert </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">UIAlertController</span><span class="token">(
</span></span><span class="line"><span class="token">        title </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Native Dialog</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,
</span></span><span class="line"><span class="token">        message </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">This is a native dialog</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,
</span></span><span class="line"><span class="token">        preferredStyle </span><span class="token" style="color: #d73a49;">=</span><span class="token"> UIAlertControllerStyleAlert
</span></span><span class="line"><span class="token">    )
</span></span><span class="line"><span class="token">    alert</span><span class="token">.addAction</span><span class="token">(
</span></span><span class="line"><span class="token">        UIAlertAction</span><span class="token">.actionWithTitle</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">OK</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,
</span></span><span class="line"><span class="token">UIAlertActionStyleDefault, </span><span class="token" style="color: #005cc5;">null</span><span class="token">)
</span></span><span class="line"><span class="token">    )
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">rootViewController </span><span class="token" style="color: #d73a49;">=</span><span class="token">
</span></span><span class="line"><span class="token">UIApplication.sharedApplication.keyWindow?.rootViewController
</span></span><span class="line"><span class="token">    rootViewController</span><span class="token">?.presentViewController</span><span class="token">(alert, animated </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">true</span><span class="token">, completion </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">null</span><span class="token">)
</span></span><span class="line"><span class="token">}
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1697"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1695">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1696'
	>
	<strong><strong><strong>Integrating in a Composable:</strong></strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1699"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun MyButtonWithNativeDialog</span><span class="token">() {
</span></span><span class="line"><span class="token">    </span><span class="token">Button</span><span class="token">(onClick </span><span class="token" style="color: #d73a49;">=</span><span class="token"> {
</span></span><span class="line"><span class="token">        </span><span class="token">showPlatformDialog</span><span class="token">()
</span></span><span class="line"><span class="token">    }) {
</span></span><span class="line"><span class="token">        </span><span class="token">Text</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Show Dialog</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">}
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1702"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1700">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1701'
	>
	Pros:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1705"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1703">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1704'
	>
	<li>Provides unrestricted access to native iOS capabilities.</li><li>Ideal for leveraging platform-specific APIs not available in SwiftUI or Compose.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1708"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1706">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1707'
	>
	Cons:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1711"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1709">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1710'
	>
	<li>Provides unrestricted access to native iOS capabilities.</li><li>Writing and maintaining platform-specific code can increase complexity.<br />
UI consistency between platforms requires additional effort.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1714"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1712">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1713'
	>
	<strong>2. Integration with <code>UIViewControllerRepresentable</code> for SwiftUI on iOS</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1717"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1715">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1716'
	>
	When dealing with existing SwiftUI components, the <code>UIViewControllerRepresentable</code> approach is invaluable. It wraps a SwiftUI view in a <code>UIViewController</code> that Kotlin Compose can embed. This is ideal for scenarios where SwiftUI views need to coexist with Compose.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1720"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1718">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1719'
	>
	Example:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1723"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1721">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1722'
	>
	<strong><strong><strong>SwiftUI Code</strong></strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1725"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">struct MySwiftUIView</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">var body:</span><span class="token"> </span><span class="token" style="color: #d73a49;">some</span><span class="token"> View </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">VStack</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token">Text(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Hello from SwiftUI!</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token">Button(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Click Me</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #005cc5;">print</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Button clicked</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1728"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1726">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1727'
	>
	<strong><strong><strong>Creating a <code>UIViewControllerRepresentable</code></strong></strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1730"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">import</span><span class="token"> </span><span class="token" style="color: #6f42c1;">SwiftUI</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">import</span><span class="token"> </span><span class="token" style="color: #6f42c1;">UIKit</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">struct MySwiftUIViewController</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #6f42c1;">UIViewControllerRepresentable </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">func makeUIViewController</span><span class="token">(</span><span class="token">context</span><span class="token">: </span><span class="token">Context</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> </span><span class="token">UIHostingController</span><span class="token">&lt;</span><span class="token">MySwiftUIView</span><span class="token">&gt;</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token">UIHostingController(</span><span class="token">rootView:</span><span class="token"> </span><span class="token">MySwiftUIView(</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">func updateUIViewController</span><span class="token">(</span><span class="token">_ uiViewController</span><span class="token">: </span><span class="token">UIHostingController</span><span class="token">&lt;</span><span class="token">MySwiftUIView</span><span class="token">&gt;</span><span class="token">, </span><span class="token">context</span><span class="token">: </span><span class="token">Context</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">&lt;em&gt;/</span><span class="token" style="color: #d73a49;">/ U</span><span class="token" style="color: #6a737d;">pdate logic, if needed&lt;/em&gt;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1733"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1731">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-1732'
	>
	<strong><strong><strong>Embedding the SwiftUI View Controller in Kotlin Compose</strong></strong></strong></h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1735"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun MyComposableView</span><span class="token">() {
</span></span><span class="line"><span class="token">    </span><span class="token">UIKitView</span><span class="token">(
</span></span><span class="line"><span class="token">        factory </span><span class="token" style="color: #d73a49;">=</span><span class="token"> { </span><span class="token">MySwiftUIViewController</span><span class="token">() },
</span></span><span class="line"><span class="token">        modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier</span><span class="token">.fillMaxSize</span><span class="token">()
</span></span><span class="line"><span class="token">    )
</span></span><span class="line"><span class="token">}
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1738"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1736">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1737'
	>
	Pros:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1741"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1739">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1740'
	>
	<li>Provides unrestricted access to native iOS capabilities.</li><li>Reuses SwiftUI components effortlessly within Kotlin Compose.<br />
Provides full access to SwiftUI&#8217;s advanced features.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1744"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1742">
	<h3	class='typography typography--size-30-text js-typography block-heading__heading'
	data-id='es-1743'
	>
	Cons:</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1747"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1745">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1746'
	>
	<li>Overhead in managing state and synchronization between Compose and SwiftUI.</li><li>Bridging between two UI frameworks may affect performance for complex UIs.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1750"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-1748">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-1749'
	>
	<strong>Navigating Kotlin Compose and iOS frameworks</strong></h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1753"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1751">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1752'
	>
	The interoperability between Kotlin Compose and iOS frameworks offers a wide range of possibilities, each with its strengths:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1756"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1754">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1755'
	>
	<li><strong>The</strong> <code><strong>expect/actual</strong></code><strong> pattern</strong> serves as the cornerstone, enabling clean abstractions and cross-platform consistency.</li><li><strong>Direct access to iOS APIs</strong> offers unmatched control for custom functionality, making it suitable for scenarios requiring precise native behavior.</li><li><strong>SwiftUI integration</strong> provides a seamless way to reuse or embed native declarative components, ideal for projects prioritizing iOS-native aesthetics.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1759"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-1757">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-1758'
	>
	Choosing the right approach depends on your project’s goals and constraints. Thanks to Kotlin Multiplatform adaptability, developers are not tied to a single solution but can leverage the best of both Compose and native frameworks to build robust, flexible, and maintainable applications.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/kotlin-multiplatform-swiftui/">Kotlin Multiplatform – Bridging Compose &amp; iOS UI Frameworks</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>