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

<channel>
	<title>Web &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/category/cross-platform/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 02 Apr 2026 16:10:25 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Using Custom URI to Compliment your Web Application</title>
		<link>https://blog.xojo.com/2026/04/06/using-custom-uri-to-compliment-your-web-application/</link>
		
		<dc:creator><![CDATA[Wayne Golding]]></dc:creator>
		<pubDate>Mon, 06 Apr 2026 14:10:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Custom URI URL Protocol]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16094</guid>

					<description><![CDATA[There are times when you will want to use the resources of your web application’s user computer, for example, printing a sales docket for a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There are times when you will want to use the resources of your web application’s user computer, for example, printing a sales docket for a Point-Of-Sale site. In this article, I will expand on William Yu’s blog post <a href="https://blog.xojo.com/2016/08/16/custom-uri-schemes-on-windows/">Custom URI Schemes On Windows</a> from 2016. Again, I’m going to use a simple alert-type application, add an Inno Setup script to install the client app, and show how to invoke that app from your web application.</p>



<p>First, I’m going to create a headless desktop application. A console application would work, but shows a command box.</p>



<p>In the Xojo IDE, create a new desktop project and delete Window1 and MainMenuBar. Then add the Opening Event Handler to App and add this code:</p>



<pre class="wp-block-code"><code>Self.AllowAutoQuit = True</code></pre>



<p>This will allow the application to quit when done.</p>



<p>Add the DocumentOpened Event Handler to App and add this code:</p>



<pre class="wp-block-code"><code>If item _ ' Using item
 .NativePath _ ' property NativePath
 .NthField(":", 1) &lt;> "AlertDemo" Then ' Compare the value left of the ":"
 Return ' If invalid return (quit)
End If
Var alert As String ' Define the variable
alert = item _ ' Using Item
 .NativePath _ ' property NativePath
 .NthField(":", 2) ' Extract the contents to the right of the ":"

alert = DecodeURLComponent(alert) ' Convert the content to plain text
MessageBox(alert) ' Show the alert
' The app will now quit</code></pre>



<p>To test you can select Shared in Build Settings.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="366" height="183" src="https://blog.xojo.com/wp-content/uploads/2026/03/image.png" alt="" class="wp-image-16095" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/image.png 366w, https://blog.xojo.com/wp-content/uploads/2026/03/image-300x150.png 300w" sizes="(max-width: 366px) 100vw, 366px" /></figure>



<p><br>And enter a value into Command Line Arguments:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="595" height="126" src="https://blog.xojo.com/wp-content/uploads/2026/03/image-1.png" alt="" class="wp-image-16096" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/image-1.png 595w, https://blog.xojo.com/wp-content/uploads/2026/03/image-1-300x64.png 300w" sizes="(max-width: 595px) 100vw, 595px" /></figure>



<p><br>Running the app in debug mode will show:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="231" height="237" src="https://blog.xojo.com/wp-content/uploads/2026/03/image-2.png" alt="" class="wp-image-16097"/></figure>



<p><br>Now build the project and create an installer using <a href="https://jrsoftware.org/isinfo.php">Inno Setup</a>.</p>



<pre class="wp-block-preformatted">[Setup]<br>AppId={{B4D9ABDA-9F58-4FE0-A5F3-3E39C28EAB59}<br>AppName=Alert Demo<br>AppVersion=1.0<br>DefaultDirName={commonpf64}\Axis Direct Ltd\Alert Demo<br>DefaultGroupName=Axis Direct<br>OutputDir=C:\Xojo Projects\Alert Demo\Installer<br>OutputBaseFilename=AlertDemoInstaller<br>Compression=lzma<br>SolidCompression=yes<br>ChangesEnvironment=yes<br>[Languages]<br>Name: "english"; MessagesFile: "compiler:Default.isl"<br>[Tasks]<br>[Dirs]<br>Name: "{app}\Alert Demo Libs"<br>[Files]<br>Source: "C:\Xojo Projects\Alert Demo\Project\Builds - Alert<br>Demo\Windows 64 bit\Alert Demo*"; DestDir: "{app}"; Flags:<br>ignoreversion<br>Source: "C:\Xojo Projects\Alert Demo\Project\Builds - Alert<br>Demo\Windows 64 bit\Alert Demo\Alert Demo Libs*"; DestDir:<br>"{app}\Alert Demo Libs"; Flags: ignoreversion<br>[Icons]<br>[Run]<br>[Registry]<br>Root: HKCR; Subkey: "AlertDemo"; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo"; ValueType: "String";<br>ValueData: "URL:AlertDemo Protocol"; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo"; ValueName: "URL Protocol";<br>ValueType: "String"; ValueData: ""; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell"; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell\open"; Flags:<br>uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell\open\command"; Flags:<br>uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell\open\command";<br>ValueType: String; ValueData: "{app}\Alert Demo.exe %1";<br>Flags: uninsdeletekey</pre>



<p>The registry section creates the registry entries per <a href="https://blog.xojo.com/2016/08/16/custom-uri-schemes-on-windows/">William’s blog post</a>.</p>



<p>Now that the application Is installed, we’ll look at the Web Application. For the sake of testing, I’m just adding a Button to a WebPage and adding the following code into the pressed event.</p>



<pre class="wp-block-code"><code>Var s As String = "Hello World"
Var Alert As String
Alert = EncodeURLComponent(s) ' Make the string URL safe
GoToURL("AlertDemo:" + Alert, True) ' Launch the app in a new tab</code></pre>



<p>And that is it!</p>



<p>For printing a docket, I would pass a unique identifier for the transaction using this method then access the data using URLConnection &amp; HandleURL.</p>



<p><em>Wayne Golding has been a Xojo developer since 2005 and is a Xojo MVP. He operates the IT Company <a href="http://www.axisdirect.nz">Axis Direct Ltd </a>which primarily develops applications using Xojo that integrate with Xero www.xero.com. Wayne’s hobby is robotics where he uses Xojo to build applications for his Raspberry Pi, often implementing IoT for remote control.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Scan Barcodes, Pick Colors, Toggle: Xojo Web in 2026r1</title>
		<link>https://blog.xojo.com/2026/03/31/scan-barcodes-pick-colors-toggle-xojo-web-in-2026r1/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:22:00 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<category><![CDATA[Xojo Web]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15969</guid>

					<description><![CDATA[If you build web apps with Xojo, 2026r1 is worth a close look. There&#8217;s a good mix of new controls and under-the-hood improvements to explore.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>If you build web apps with Xojo, 2026r1 is worth a close look. There&#8217;s a good mix of new controls and under-the-hood improvements to explore. Exciting times!</p>



<h2 class="wp-block-heading">New Controls</h2>



<p>Three new controls have been added to the Web framework in this release, aiming to close the difference gap between Web and the other project types.</p>



<p><code>WebSwitch</code>&nbsp;is a toggle control that mobile developers will already be familiar with. It&#8217;s been available on iOS and Android for a while. It&#8217;s now available for web projects too, so if you&#8217;ve been approximating a toggle switch using a styled checkbox, you can finally retire that workaround.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="690" src="https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-1024x690.png" alt="" class="wp-image-15992" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-1024x690.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-300x202.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-768x517.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-1536x1035.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-2048x1380.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><code>WebColorPicker</code> brings color selection to web apps in the same way <code>DesktopColorPicker</code> does for desktop. Drop it in from the Library, wire up the event and you have a color picker the Xojo way.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="731" src="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-1024x731.png" alt="" class="wp-image-15994" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-1024x731.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-768x548.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-1536x1096.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-2048x1461.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This is how <code>WebColorPicker</code> looks like in your browser:</p>



<figure class="wp-block-video"><video height="1274" style="aspect-ratio: 1488 / 1274;" width="1488" controls src="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-browser.mp4"></video></figure>



<p>The third new control adds barcode reading support. Your web app can now read barcodes directly from the user&#8217;s camera, from desktop or mobile browsers. This opens up a lot of practical use cases: Inventory systems, ticketing, product lookups, that previously would have pushed you toward a native mobile app.</p>



<p>Again, drop the Barcode control into your project and implement the events:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="747" src="https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-1024x747.png" alt="" class="wp-image-15995" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-1024x747.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-300x219.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-768x560.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-1536x1120.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-2048x1494.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>That&#8217;s it! Your web apps can scan a great variety of barcodes now. Including QR, Data Matrix, Aztec, PDF 417 and much more!</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="471" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1-471x1024.png" alt="" class="wp-image-16007" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1-471x1024.png 471w, https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1-138x300.png 138w, https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1.png 555w" sizes="auto, (max-width: 471px) 100vw, 471px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="471" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1-471x1024.png" alt="" class="wp-image-16008" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1-471x1024.png 471w, https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1-138x300.png 138w, https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1.png 555w" sizes="auto, (max-width: 471px) 100vw, 471px" /></figure>
</div>
</div>



<h2 class="wp-block-heading">Icons on WebButtons</h2>



<p><code>WebButton</code>&nbsp;now has an&nbsp;<code>Icon</code>&nbsp;property. You can assign any&nbsp;<code>WebPicture</code>&nbsp;to it, or use one of the Bootstrap icons that are already bundled with the framework. It&#8217;s a small addition, but it makes a noticeable difference when building action-heavy interfaces where a label alone doesn&#8217;t communicate enough at a glance.</p>



<p>Add a button into your project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="690" src="https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-1024x690.png" alt="" class="wp-image-16001" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-1024x690.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-300x202.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-768x517.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-1536x1035.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-2048x1380.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Configure its Icon property in the <code>Opening</code> event:</p>



<pre class="wp-block-code"><code>Me.Icon = WebPicture.BootstrapIcon("key-fill")</code></pre>



<p>If you don&#8217;t specify a color in BootstrapIcon, it will inherit the button caption color in this case. This is the easiest way to support Dark Mode with the new <code>WebButton.Icon</code> property, without doing any special tricks.</p>



<p>Here is how it looks like at runtime:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-1024x889.png" alt="" class="wp-image-15999" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-300x261.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-768x667.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-1536x1334.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light.png 1612w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Dark Mode:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-1024x889.png" alt="" class="wp-image-16000" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-300x261.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-768x667.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-1536x1334.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark.png 1612w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">WebLabel: Semantic HTML and Proper Element Types</h2>



<p>Two related changes landed for&nbsp;<code>WebLabel</code>&nbsp;in this release. The first is a correctness fix: the control was previously rendered using the HTML&nbsp;<code>&lt;label&gt;</code>&nbsp;element, which is semantically meant to label form inputs, not to display general text. That has been corrected.</p>



<p>The more interesting addition is that you can now choose which HTML element&nbsp;<code>WebLabel</code>&nbsp;renders as. If you want a label to be an&nbsp;<code>&lt;h1&gt;</code>&nbsp;or an&nbsp;<code>&lt;h2&gt;</code>, you can set that directly in the Inspector. This is useful not just for visual styling, but for accessibility tools and search engines that rely on page structure to understand content hierarchy.</p>



<p>Improving both, accessibility and making search engines happier, are some of our goals for 2026. You will continue seeing improvements in this sense.</p>



<h2 class="wp-block-heading">WebTextArea Gets AddText</h2>



<p><code>WebTextArea</code>&nbsp;now has an&nbsp;<code>AddText</code>&nbsp;method, consistent with how the control works on Desktop and Mobile. If you&#8217;re writing code that targets multiple platforms, this kind of parity saves you from having to check which target you&#8217;re on, before appending text.</p>



<h2 class="wp-block-heading">Scale Indicator on WebMapViewer</h2>



<p><code>WebMapViewer</code>&nbsp;now has a&nbsp;<code>HasScaleIndicator</code>&nbsp;property. When enabled, a small visual scale appears on the map showing real-world distance. It makes a difference in apps where users need spatial context. Field work, logistics or anything where &#8220;how far is that?&#8221; is a question users might actually ask.</p>



<h2 class="wp-block-heading">Performance and Modernization Under the Hood</h2>



<p>A few changes in this release won&#8217;t be immediately visible, but they improve things for everyone.</p>



<p>Bootstrap has been updated to v5.3.8 which fixes some issues introduced in v5.3.7 impacting Xojo. The TypeScript compiler has been updated to v5.9.3, and the compilation target has been bumped from ES6 to ES2020. Unused code in the Web Framework has been cleaned up to reduce the compiled bundle size.</p>



<p>Xojo has also removed its own internal usage of Modernizr. The library is still present for now so existing apps that rely on it won&#8217;t break, but it&#8217;s no longer used by the framework itself and will be removed in a future release.</p>



<p>If you&#8217;ve been meaning to audit your web app for performance, this is a good moment to look at&nbsp;<code>SendEventsInBatches</code>&nbsp;and&nbsp;<code>LazyLoadDependencies</code>&nbsp;on&nbsp;<code>WebSession</code>&nbsp;as well. Both now default to&nbsp;<code>True</code>&nbsp;on new projects, so if your existing app has them disabled, it&#8217;s worth trying them out. These properties have been around for a while already but were turned off by default.</p>



<h2 class="wp-block-heading">API Consistency Cleanups</h2>



<p>A few methods have been deprecated in favour of names that are consistent with the rest of the framework:</p>



<ul class="wp-block-list">
<li><code>WebApplication.AutoQuit</code>&nbsp;→&nbsp;<code>AllowAutoQuit</code></li>



<li><code>WebListBox.ReloadData</code>&nbsp;→&nbsp;<code>ReloadFromDataSource</code></li>



<li><code>WebRadioGroup.RemoveAllRows</code>&nbsp;→&nbsp;<code>RemoveAll</code>, and&nbsp;<code>RemoveRowAt</code>&nbsp;→&nbsp;<code>RemoveAt</code></li>
</ul>



<p>Your existing code will still compile, but it&#8217;s worth updating these when you get a chance.</p>



<h2 class="wp-block-heading">Wrapping Up</h2>



<p>Between new controls, better HTML semantics, and a leaner runtime, 2026r1 is a worthwhile update for anyone building web apps with Xojo. Check out the&nbsp;<a href="https://documentation.xojo.com/resources/release_notes/2026r1.html">full release notes</a>&nbsp;for the complete list of changes.</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-browser.mp4" length="707463" type="video/mp4" />

			</item>
		<item>
		<title>New WebUserAuthentication Control: Look, Mom, No Passwords!</title>
		<link>https://blog.xojo.com/2025/12/09/new-webuserauthentication-control-look-mom-no-passwords/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:30:29 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[Passkey]]></category>
		<category><![CDATA[Passwords]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15321</guid>

					<description><![CDATA[The web framework has a new control available in the Library, WebUserAuthentication. Now that Passkeys have arrived, let&#8217;s explore this feature! Passkeys Demo In this&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The web framework has a new control available in the Library, <code>WebUserAuthentication</code>. Now that Passkeys have arrived, let&#8217;s explore this feature!</p>



<h2 class="wp-block-heading">Passkeys Demo</h2>



<p>In this demo, we will be creating a new account using just our email. Using a platform authenticator, like Apple Passkeys or Windows Hello will make this pretty easy. They are integrated in the operating system and synced across devices. I will be using macOS with the integrated Passwords app, but this is supported in Windows through Windows Hello, or you could store, sync and use Passkeys using a Google Chrome Profile.</p>



<figure class="wp-block-video"><video height="1240" style="aspect-ratio: 1472 / 1240;" width="1472" controls src="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signup.mp4"></video></figure>



<p>As you can see, there is no intermediate step. No need to use a separate app to store your passwords securely. A Passkey will be generated and stored in the authenticator in one simple step. This Passkey will be automatically synced across devices and available on my iPhone.</p>



<p>Opening the Password application, I already can confirm my new Passkey has been stored for &#8220;localhost&#8221;. Notice the user name is also there, meaning you won&#8217;t need to fill it during the login process.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="710" src="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-1024x710.png" alt="" class="wp-image-15323" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-1024x710.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-300x208.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-768x533.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-1536x1065.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app.png 1716w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The username isn&#8217;t important or even required, it&#8217;s just to display a friendly name for this user. A Passkey will include the user ID, which can be any arbitrary String you want. In my example, I&#8217;ve used the new <a href="https://documentation.xojo.com/api/math/random.html#random-uuid" target="_blank" rel="noreferrer noopener">Random.UUID method</a>, but this is completely up to you. And this is transparent for the end user.</p>



<p>Now, let&#8217;s try to login:</p>



<figure class="wp-block-video"><video height="1240" style="aspect-ratio: 1472 / 1240;" width="1472" controls src="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signin.mp4"></video></figure>



<p>That&#8217;s it!</p>



<p>Another thing to notice is, while I have several Passkeys for different websites, only the relevant Passkey can be used. This makes Phishing attacks useless. End users won&#8217;t be able to use a Passkey anywhere else, just on the website where it has been created. And also, users won&#8217;t be able to send their password by mistake to an attacker because … they can&#8217;t!</p>



<p>For web application developers, another interesting thing to note is that you won&#8217;t be able to store a Passkey insecurely. Even if your database gets compromised, a hacker won&#8217;t be able to use the stored public keys to authenticate those users with another service. To make it easier to understand, you will be storing a lock, not the key used to open it.</p>



<h2 class="wp-block-heading">Other User Journeys</h2>



<p>My demo is just the classic email / password sign up / sign in workflow, but without using a password. Passkeys is based on WebAuthn (part of FIDO2) and there are several ways you can use this technology in your web application. For example, you could use a shared computer and still be able to securely log in using your mobile. The platform will display a QR code you can read with your phone camera, and grant the access from your personal device.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-1024x889.png" alt="" class="wp-image-15325" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-300x260.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-768x666.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-1536x1333.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In.png 1604w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In my example application, the user can sign up using different emails. If the Passwords app encounters more than one for my domain it will allow the user to specify the Passkey to use:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-1024x889.png" alt="" class="wp-image-15326" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-300x260.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-768x666.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-1536x1333.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_.png 1604w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Xojo will take care of preparing the <code>WebAuthn</code> steps, verifying signatures and doing the common busy work for you. You will have to decide which workflow makes sense for your application and perform any further verifications, like sending a verification email on register, to ensure this user owns that account.</p>



<h2 class="wp-block-heading">Multi-Factor Authentication</h2>



<p>If you already require your users to authenticate with a username (or email) and a password, you could use <code>WebUserAuthentication</code> as a second factor. That means the user will need to provide something this person knows (a username and password combination) in addition to something the user has (the authenticator device)</p>



<p>Other common multi-factor authentication schemes are email magic links and time-based one-time passwords, <em>&#8220;TOTP&#8221;</em>.</p>



<p>More factors equal better security, of course. But as usual when it comes to security, you&#8217;ll have to find the sweet spot between secure and comfortable.</p>



<h2 class="wp-block-heading">Usernameless + Passwordless Authentication … Wait, What?!?</h2>



<p><em>&#8220;How can I authenticate without providing my username or email?&#8221;</em>. This is where real new possibilities arise. When you use a username with a password that only Chuck Norris and you know, this becomes a &#8220;proof of identity&#8221; (at least in theory, in practice a hacker could compromise an account using a weak password)</p>



<p>When using an authenticator without a username or password, it becomes a &#8220;proof of possession&#8221; of the authenticator device.</p>



<p>Again, think about it as a locker&#8217;s lock and a key. Everyone can see the lock, but only people with the correct key can open it. The public key would be the door&#8217;s lock, while the authenticator device would be the key. You can share the key with another person you trust to grant this person access to the contents behind that door. The difference with a real-life lock is that we will be using a really secure one, with a security key.</p>



<p>As long as you can proof you have a valid &#8220;key&#8221; to authenticate, you are granted to continue.</p>



<p>Consider the following scenario. The company could have a web application that uses a traditional username + password authentication but, for really special activities, the user needs to authenticate with a physical USB key authenticator device that is shared by everyone in the office.</p>



<p>Other use cases are obviously when privacy is involved. A private journal, or a private blogging service, voting. The inconvenience in this case is the user won&#8217;t be able to recover the account if they lose access to the authenticator. In this case, you might want to offer a different recovery solution, like printing a very long recovery code. If they also lose the recovery code, they will permanently lose the account.</p>



<h2 class="wp-block-heading">How To Use The New Control</h2>



<p>As you do with any other non-visual control, like a <code>WebTimer</code>, you can just drop the new <code>WebUserAuthentication</code> control into your WebPage.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="491" src="https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-1024x491.png" alt="" class="wp-image-15327" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-1024x491.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-300x144.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-768x368.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-1536x736.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-2048x982.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Then configure its properties. The most important one is the Domain field. It must match the domain name where your application will be deployed. If you want to test it locally without using HTTPS, it must be &#8220;localhost&#8221; (&#8220;127.0.0.1&#8221; won&#8217;t work)</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="666" height="269" src="https://blog.xojo.com/wp-content/uploads/2025/08/Appearance-copia.png" alt="" class="wp-image-15328" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/Appearance-copia.png 666w, https://blog.xojo.com/wp-content/uploads/2025/08/Appearance-copia-300x121.png 300w" sizes="auto, (max-width: 666px) 100vw, 666px" /></figure>



<p>There are four events available:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="656" height="250" src="https://blog.xojo.com/wp-content/uploads/2025/11/Captura-de-pantalla-2025-11-20-a-las-10.50.33.png" alt="" class="wp-image-15544" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/Captura-de-pantalla-2025-11-20-a-las-10.50.33.png 656w, https://blog.xojo.com/wp-content/uploads/2025/11/Captura-de-pantalla-2025-11-20-a-las-10.50.33-300x114.png 300w" sizes="auto, (max-width: 656px) 100vw, 656px" /></figure>



<p>You can use <code>RegistrationSucceeded</code> and <code>AuthenticationSucceeded</code> to interact with your Database, store the details and redirect the user to their dashboard.</p>



<p>In <code>RegistrationSucceeded</code>, a <code>WebAuthenticationCredential</code> will be given to you. This is a data transfer object with the following properties you need to store in your database:</p>



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



<li>PublicKey</li>



<li>AuthenticationAttempts</li>



<li>DisplayName</li>
</ul>



<p>Error will be fired when something goes wrong. A message will also show with the details about what happened, but it isn&#8217;t meant to be shared with the end user. During the sign up and sign in processes, you should display generic messages for security, to avoid letting bad actors know what&#8217;s going on. If you need to inform the user something related to these messages, you can send them an automated email instead.</p>



<p><code>CredentialRequested</code> will be fired during the authentication ceremony. A userId and a credentialId will be given to you, and you should return a new <code>WebAuthenticationCredential</code> instance with the details coming from the <code>RegistrationSucceededEvent</code>.</p>



<p>Also, when <code>AuthenticationSucceeded</code> happens, the event will come with an <code>authenticationAttempts</code> parameter. This will be an incremental value used to update your credentials. This is part of the <code>WebAuthn</code> protocol sign in ceremony used to detect cloned authenticators, which is supported by Xojo. Please notice this value might come always as &#8220;0&#8221; when using Safari, for example, but Google Chrome will increase its value each time.</p>



<p>You can initiate a Registration or Authentication ceremony by calling Register or Authenticate, respectively.</p>



<ul class="wp-block-list">
<li><strong>Register</strong>(userId As String, username As String = &#8220;&#8221;, displayName As String = &#8220;&#8221;)<br>The parameter userId is required, the new credential will be built specifically for it. It can be anything that makes sense in your application, like an auto-incremental number or a random UUID . The other parameters are meant for giving the credential a friendly name. The username could be a nickname, or an email. In workflows where you allow the user to store more than one passkey, the displayName could be something like &#8220;Backup key&#8221;.</li>



<li><strong>Authenticate</strong>(Optional allowCredentials() As String)<br>This will initiate the authentication ceremony. You can optionally pass an array of credential IDs, allowed for the user trying to get access to the protected resource.</li>
</ul>



<h2 class="wp-block-heading">Adoption and Compatibility</h2>



<p>Not every user may know they even exist, what they are, how they work or if they will be more secure than using their pet&#8217;s name and birthdate. This can cause some friction. Other users that adopted the usage from day one might have at least two physical USB keys. They expect your application to allow them to enter more than one, just in case they lose their main USB key.</p>



<p>Passkeys are here to stay and their adoption will continue growing on web services. That said, depending on the combination of operating system and browser, there are some gotchas. Google Chrome or Firefox should work on every operating system. Apple users will probably obtain the best user experience if they&#8217;re tied to this ecosystem. Linux users using alternative browsers could experience some challenges.</p>



<p>If compatibility is a must for your application, you should still offer an alternative to Passkeys. For example, legacy passwords, or &#8220;magic login links&#8221; sent by email.</p>



<h2 class="wp-block-heading">Wrapping Up</h2>



<p>We are sure Passkeys will be the norm in the coming years. Read more in the <a href="https://documentation.xojo.com/api/web/webauthenticationcredential.html" target="_blank" rel="noreferrer noopener">Xojo Docs</a>. Xojo is ready to embrace them and you can start adopting them in your Xojo Web application today!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signup.mp4" length="684699" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signin.mp4" length="435817" type="video/mp4" />

			</item>
		<item>
		<title>Checking Out Xojo Libraries</title>
		<link>https://blog.xojo.com/2025/12/09/checking-out-xojo-libraries/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:29:31 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15569</guid>

					<description><![CDATA[The ability to create a compiled Library with Xojo has been a long-requested feature. Starting with 2025 Release 3, Library support is now available as&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The ability to create a compiled Library with Xojo has been a long-requested feature. Starting with 2025 Release 3, Library support is now available as a preview. Here’s more information about what it is and how you can use it.</p>



<h2 class="wp-block-heading">What is a Library?</h2>



<p>A Library is a collection of pre-written, reusable code containing methods, classes and UI.&nbsp;Up until now, the way to distribute a Library for use with Xojo was to create a Plugin or to manually re-use project items across projects. Both have pros and cons.</p>



<p>Plugins are compiled and do not expose source code, but plugins cannot be created using Xojo itself and are typically created using C/C++ along with the Xojo Plugin SDK. Sharing project items is fine for internal projects or open-source projects, but less ideal for commercial libraries. They can be harder to manually add to a project and are recompiled along with the project, slowing the debug process.</p>



<p>With a Xojo Library, you can now create your own compiled Library using Xojo itself. This Library can contain nearly any Xojo project item and can be easily used in other Xojo projects because it is distributed as a single file.</p>



<p>At a high-level, you create your Library in Xojo, add your project items to it and built it into a Library package file. Other projects can then use this Library package, which gives them access to the items you included in the Library.</p>



<h2 class="wp-block-heading">Creating a Library</h2>



<p>Here is a brief overview of how you create a Xojo Library:</p>



<ol class="wp-block-list">
<li>In a Desktop, Web, Console or iOS project add a Library by choosing Insert-&gt;Library.</li>



<li>Add the project items you want to the Library. Any Xojo project item is supported, except for Worker.</li>



<li>Build the project. It will build the main app (which should serve as a test app for your Library) and a separate Library package file (with extension .xojo_library).</li>



<li>You can put this Library package alongside another project (on the drive) and it will be loaded when that project is opened by Xojo. You can then use the classes, methods and UI contained in the Library within your project. If you instead put the Library in the Plugins folder, then it will be available for all projects.</li>
</ol>



<p>This is all best demonstrated by a quick example. Go ahead and create a Desktop project and add a Library to it, which adds a Library1 project item to the Navigator. Change its name using the Inspector to LibHello.</p>



<p>While LibHello is selected, choose Insert-&gt;Class. This adds Class1 to it. This new class is now part of the Library. With Class1 selected, change its name to StringStuff.</p>



<p>You can now add whatever methods or properties you want to the class. For our example purposes here we will add a simple method that reverses a string.</p>



<pre class="wp-block-code"><code>Public Function ReverseString(s As String) As String
  Var newString As String
  
  For Each c As String In s.Characters
    newString = c + newString
  Next
  
  Return newString
End Function</code></pre>



<p>The Library could contain many other things of course, but to keep things simple this Library will have just the single class with its single method. Here&#8217;s what it looks like in the project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="311" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-1024x311.png" alt="" class="wp-image-15570" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-1024x311.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-300x91.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-768x233.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x.png 1382w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The first thing to do is to test this Library ReverseString method. Add a button to Window1 and have it call the function, verifying the result.</p>



<pre class="wp-block-code"><code>Var stuff As New StringStuff
Var result As String = stuff.ReverseString("Xojo")

MessageBox(result)</code></pre>



<p>When you run, you can see the output:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="744" height="584" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x.png" alt="" class="wp-image-15572" style="width:407px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x.png 744w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x-300x235.png 300w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>



<p>So far this is all not much different than you would normally be doing with a Xojo project. The next step is to create the Library package for use by other projects.</p>



<p>In the Build Settings area, select Shared. This is where you can enter some information about the Library that can be seen by those that use it.</p>



<ul class="wp-block-list">
<li>In the Version field, enter &#8220;1.0&#8221;.</li>



<li>In the Copyright field, enter &#8220;Acme, Inc.&#8221;</li>



<li>In the Description field, enter &#8220;A Xojo Library test.&#8221;</li>
</ul>



<p>Also in the Build Settings area, check the boxes for the platforms you want the Library to work on. In most situations, you will want to select macOS, Windows and Linux.</p>



<p>Now click Build. This builds the app as usual, but also creates a separate Library package file (LibHello.xojo_library for this example) that can be used with other projects.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="558" src="https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1024x558.png" alt="" class="wp-image-15577" style="width:590px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1024x558.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-300x163.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-768x418.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1536x837.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1.png 1542w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Using a Library</h2>



<p>Now that you&#8217;ve created your Library package, you can use it with other Xojo projects. The Library built above was created within a Desktop project, so it can only be used with other Desktop projects. So the first thing to do is to create a new Desktop project (call it MyTest), save it and close it.</p>



<p>Once it is saved, go to Finder or Explorer and place a copy of the LibHello.xojo_library file (from its build location) alongside this saved project file.</p>



<p>Go back to Xojo and open the MyTest project. The project will open normally, but the Library will also be loaded up as well. You can see this by showing the Xojo About window and going to the Plugins &amp; Libraries tab. There you will see the Library name along with the information you entered about it earlier. (Double-click on the Library row to show the description.)</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="726" src="https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-1024x726.png" alt="" class="wp-image-15578" style="width:664px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-1024x726.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-300x213.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-768x544.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow.png 1524w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Going back to the MyTest project, you can now use the Library with it. Add a button to the window and have it call the StringReverse function the same way you did before:</p>



<pre class="wp-block-code"><code>Var stuff As New StringStuff
Var result As String = stuff.ReverseString("Xojo")

MessageBox(result)</code></pre>



<p>Now run the project and it will use the class and its method just as if it is part of the project.</p>



<p>That&#8217;s the basics of how to create and use a Library. You can of course include whatever you want in the Library, but as with any library it is usually a good idea to keep things well-organized.</p>



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



<ul class="wp-block-list">
<li>A Library package (which uses ZIP) contains compiled code and definitions of the public API in that code.</li>



<li>Only a single Library project item can be added to a project when developing.</li>



<li>A project can use any number of Library packages.</li>



<li>For a built library to work on all OS platforms, then those platforms must be selected before building it.</li>



<li>Libraries only support 64-bit builds.</li>



<li>Library packages are placed alongside the project file and are loaded when the project is loaded.</li>



<li>Library packages can also be placed in the Plugins folder. These libraries will be loaded separately for each project.</li>



<li>If items in your Library have dependencies outside the Library, then the Library package will not be usable in another project without those dependencies. For example, if a Library class method references a class in the main project, then it will build without an error (because the main project is available), but if you use that Library in another project you will get linker errors.</li>
</ul>



<h2 class="wp-block-heading">Why a Preview?</h2>



<p>We are referring to this initial version of Xojo Libraries as a preview release because it is very new and we want to give more developers a chance to test with it so we can iron out issues. We encourage you to try moving your existing reusable code collections over to a Library to help test, while also improving your workflow. If you have any open-source projects that are essentially a Library, you might try building them into a Xojo Library package as well.</p>



<p>You can make Library packages available publicly, but you should probably tag them as a preview, beta or test version until we remove the preview label.</p>



<p>Read more about Libraries in the <a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">Xojo Documentation</a>. Check out these open-source projects on GitHub that have recently been updated for API 2.0 and now have a Library that you can download from the Releases section:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/xojo/VB" target="_blank" rel="noreferrer noopener">Visual Basic Library</a></li>



<li><a href="https://github.com/xojo/FM" target="_blank" rel="noreferrer noopener">FileMaker Library</a></li>



<li><a href="https://github.com/paullefebvre/winapilib" target="_blank" rel="noreferrer noopener">WinAPI Library</a></li>
</ul>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How To Share Your Local Xojo Web App to the Internet Using ngrok</title>
		<link>https://blog.xojo.com/2025/08/07/how-to-share-your-local-xojo-web-app-to-the-internet-using-ngrok/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Thu, 07 Aug 2025 14:52:22 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[Remote Testing]]></category>
		<category><![CDATA[Web App Testing]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Webhook Development]]></category>
		<category><![CDATA[Xojo Web]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15075</guid>

					<description><![CDATA[Have you ever built an amazing Xojo web application locally on your machine and wished you could instantly share it with a client, test it&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Have you ever built an amazing Xojo web application locally on your machine and wished you could instantly share it with a client, test it on a real mobile device outside your local network, or integrate it with a webhook service like Stripe or Twilio? If so, you know the pain of needing a publicly accessible URL for your locally running app.</p>



<p>This is where&nbsp;ngrok&nbsp;comes in: a fantastic tool that creates secure tunnels to your localhost, making your locally running Xojo web app accessible from anywhere in the world. It&#8217;s a game-changer for testing, demonstrations, and rapid development.</p>



<h2 class="wp-block-heading">What is ngrok and Why Xojo Developers Need It?</h2>



<p>At its core, ngrok is a command-line tool that creates a secure, public URL for a service running on your local machine. Think of it as a temporary bridge from the internet directly to your computer, bypassing firewalls and NAT configurations.</p>



<p>For Xojo Web developers, this offers a wealth of benefits:</p>



<ul class="wp-block-list">
<li><strong>Real-device Testing:</strong>&nbsp;Test your Xojo web app&#8217;s responsiveness and functionality on actual mobile phones, tablets, or other computers, even if they&#8217;re not on your local Wi-Fi network.</li>



<li><strong>Instant Demonstrations:</strong>&nbsp;Share your work-in-progress with clients, colleagues, or friends without the need of deploying to a remote server. They just need the ngrok-provided URL!</li>



<li><strong>Webhook Development:</strong>&nbsp;Many third-party services (payment gateways, messaging platforms, etc.) use webhooks to notify your application of events. These webhooks require a public URL to send data to. ngrok provides this, making local webhook development a breeze.</li>



<li><strong>Debugging Public-Facing Issues:</strong>&nbsp;Sometimes, an issue only appears when your app is publicly accessible. ngrok allows you to debug such scenarios without a full deployment cycle.</li>
</ul>



<p>It&#8217;s truly a must-have tool in your Xojo Web development toolkit!</p>



<h2 class="wp-block-heading">Getting Started with ngrok</h2>



<p>Before we connect our Xojo app, we need to get ngrok set up.</p>



<h3 class="wp-block-heading">Step 1: Download ngrok</h3>



<p>Head over to the official ngrok website:&nbsp;<a href="https://ngrok.com/download" target="_blank" rel="noreferrer noopener">https://ngrok.com/download</a>.</p>



<p>Download the version appropriate for your operating system (Windows, macOS, Linux).</p>



<h3 class="wp-block-heading">Step 2: Unzip and Place</h3>



<p>Once downloaded, you&#8217;ll get a single executable file (e.g.,&nbsp;<code>ngrok.exe</code>&nbsp;on Windows,&nbsp;<code>ngrok</code>&nbsp;on macOS/Linux). Unzip it and place it in a convenient location. I recommend creating a dedicated folder for it, or placing it somewhere easily accessible from your terminal or command prompt.</p>



<h2 class="wp-block-heading">Preparing Your Xojo Web App</h2>



<p>Xojo Web applications are self-contained web servers. When you run a Xojo Web app in debug mode or build it for deployment, it listens for incoming connections on a specific port. By default, Xojo Web apps usually listen on&nbsp;port 8080.</p>



<p>Let&#8217;s quickly ensure your Xojo Web app is ready:</p>



<ol class="wp-block-list">
<li><strong>Open your Xojo Web Project:</strong>&nbsp;Open any existing Xojo Web project, or create a new one for testing.</li>



<li><strong>Run in Debug Mode:</strong>&nbsp;Click the &#8220;Run&#8221; button in the Xojo IDE. Your web app will launch in your default browser, at&nbsp;<code>http://localhost:8080</code>.</li>
</ol>



<h2 class="wp-block-heading">Tunneling Your Xojo App with ngrok</h2>



<p>Now for the magic! With your Xojo Web app running locally, we&#8217;ll open a tunnel to it using ngrok.</p>



<h3 class="wp-block-heading">Step 1: Open Terminal/Command Prompt</h3>



<p>Open your system&#8217;s terminal (macOS/Linux) or Command Prompt/PowerShell (Windows).</p>



<h3 class="wp-block-heading">Step 2: Navigate to ngrok Directory (if needed)</h3>



<p>If you didn&#8217;t place the&nbsp;<code>ngrok</code>&nbsp;executable in a system PATH location, navigate to the directory where you unzipped&nbsp;<code>ngrok</code>&nbsp;using the&nbsp;<code>cd</code>&nbsp;command. For example:</p>



<pre class="wp-block-code"><code>cd /path/to/your/ngrok/folder</code></pre>



<h3 class="wp-block-heading">Step 3: Run the ngrok Command</h3>



<p>Now, execute the&nbsp;<code>ngrok</code>&nbsp;command to create the tunnel. Since Xojo Web apps typically run on port 8080, the command will be:</p>



<pre class="wp-block-code"><code>ngrok http 8080</code></pre>



<ul class="wp-block-list">
<li><code>http</code>: Specifies that we&#8217;re tunneling an HTTP service.</li>



<li><code>8080</code>: This is the port your Xojo Web app is listening on. If you&#8217;ve configured your Xojo app to use a different port (e.g., in the Build Settings), make sure to use that port number instead.</li>
</ul>



<p>After running the command, ngrok will output information about the tunnel it has created. You&#8217;ll see output similar to this:</p>



<pre class="wp-block-code"><code>ngrok                                                                            (Ctrl+C to quit)

Session Status                online
Account                       Account Name (Free)
Version                       3.x.x
Region                        United States (us)
Forwarding                    https://a52b-20-40-100-120.ngrok-free.app -&gt; http://localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
</code></pre>



<p>The most important lines here are the&nbsp;<code>Forwarding</code>&nbsp;lines. These provide you with the public URLs that point to your Xojo web app.</p>



<h2 class="wp-block-heading">Testing Your Public Xojo App</h2>



<p>With the ngrok tunnel active, your Xojo web app is now live to the world!</p>



<ol class="wp-block-list">
<li><strong>Copy the HTTPS URL:</strong>&nbsp;Copy the&nbsp;<code>https://</code>&nbsp;URL provided by ngrok.</li>



<li><strong>Test It:</strong>
<ul class="wp-block-list">
<li>Paste this URL into any web browser, on any device, anywhere with an internet connection.</li>



<li>Send the URL to a friend or client to get their feedback.</li>



<li>Test it on your mobile phone&#8217;s browser using its cellular data connection (not your local Wi-Fi) to simulate a truly external connection.</li>
</ul>
</li>
</ol>



<p>You&#8217;ll see your Xojo web app load as if it were hosted on a remote server!</p>



<p>To stop the ngrok tunnel, press Ctrl+C in the console.</p>



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



<p>ngrok can be an indispensable tool for any Xojo Web developer. It transforms the challenging task of exposing a local web app into a simple, one-line command. Whether you&#8217;re testing on diverse devices, showcasing your progress to clients, or integrating with external webhook services, ngrok streamlines your workflow and lets you focus on what you do best: building amazing applications with Xojo.</p>



<p>Give ngrok a try on your next Xojo Web project, and prepare to be amazed by the convenience it offers!</p>



<p>What if we create a Build Step script to automatically run ngrok when needed? Share your experiences and tips in the <a href="https://forum.xojo.com/" target="_blank" rel="noreferrer noopener">Xojo forums</a>!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Deploy Xojo Web Apps with Caddy Reverse Proxy</title>
		<link>https://blog.xojo.com/2025/08/04/deploy-xojo-web-apps-with-caddy-reverse-proxy/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Mon, 04 Aug 2025 18:45:28 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Xojo Web]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15201</guid>

					<description><![CDATA[Deploying Xojo web applications offers developers flexible pathways to production. For devs prioritizing minimal infrastructure management,&#160;Xojo Cloud&#160;provides a fully-managed solution with automatic scaling, SSL, and&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Deploying Xojo web applications offers developers flexible pathways to production. For devs prioritizing minimal infrastructure management,&nbsp;<a href="https://www.xojo.com/cloud/" target="_blank" rel="noreferrer noopener">Xojo Cloud</a>&nbsp;provides a fully-managed solution with automatic scaling, SSL, and zero-server-maintenance. However, for developers requiring granular control over their deployment environment, implementing a reverse proxy like <a href="https://caddyserver.com/" data-type="link" data-id="https://caddyserver.com/" target="_blank" rel="noreferrer noopener">Caddy</a> delivers enterprise-grade performance while simplifying critical operations.</p>



<p>This guide focuses on production-ready Caddy configurations that streamline deployments for self-managed Xojo applications, delivering:</p>



<ul class="wp-block-list">
<li>Automated TLS certificate management</li>



<li>Native load balancing between instances</li>



<li>Simplified configuration compared to traditional proxies</li>



<li>Header optimizations specifically tuned for Xojo’s framework</li>
</ul>



<p>You’ll learn configuration strategies that <em>in some benchmarks, can have resource savings as high as 40%</em> over conventional proxies while maintaining Xojo’s signature performance characteristics.</p>



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



<h3 class="wp-block-heading">Core Configuration Strategies</h3>



<p><strong>Basic Reverse Proxy Setup</strong></p>



<pre class="wp-block-code"><code>yourdomain.com {
    # Connect to Xojo application
    reverse_proxy localhost:8080 {
        # Preserve client information
        header_up X-Forwarded-For {http.request.remote.host}
        header_up Host {http.request.host}
    }
    
    # Automate HTTPS
    tls admin@yourdomain.com
}</code></pre>



<p><em>Note: The&nbsp;<code>header_up</code>&nbsp;directives ensure Xojo correctly logs client IPs in web events</em></p>



<p><strong>Load Balancing Across Instances</strong></p>



<pre class="wp-block-code"><code>app.yourdomain.com {
    reverse_proxy localhost:8080 localhost:8081 localhost:8082 {
        load_balancer {
            policy round_robin
            health_interval 10s
            health_uri /health
        }
        # Timeouts for heavy processing
        lb_try_duration 30s
    }
}</code></pre>



<p><strong>Security Hardening Measures</strong></p>



<pre class="wp-block-code"><code>yourdomain.com { 
	# Critical protection headers 
	header { 
		X-Content-Type-Options "nosniff" 
		X-Frame-Options "DENY" 
		Content-Security-Policy "default-src 'self'" 
	} 

	# Rate limiting for API endpoints 
	route /api/* { 
		rate_limit { 
			zone api 
			burst 100 
			period 10s 
		} 
	} 
}</code></pre>



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



<h3 class="wp-block-heading">Production-Ready Deployment Scripts</h3>



<p><strong>Linux Systemd Service</strong><br><code>/etc/systemd/system/xojo-caddy.service</code>:</p>



<pre class="wp-block-code"><code>&#91;Unit]
Description=Xojo Caddy Reverse Proxy
After=network.target

&#91;Service]
Type=simple
User=caddy
ExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile
Restart=on-failure
RestartSec=5

&#91;Install]
WantedBy=multi-user.target</code></pre>



<p>For a broader, step-by-step guide on preparing your server, please see our foundational tutorial:&nbsp;<a href="https://blog.xojo.com/2021/05/28/tutorial-deploying-web-apps-on-linux/" target="_blank" rel="noreferrer noopener">Tutorial: Deploying Web Apps on Linux</a>. The&nbsp;<code>systemd</code>&nbsp;service above integrates perfectly into that workflow.</p>



<p><strong>Windows Deployment Package</strong><br><code>Xojo-Caddy.bat</code>:</p>



<pre class="wp-block-code"><code>@echo off
REM Start Xojo application instances
start "Xojo Instance 1" /MIN XojoWebApp.exe --port=8080
start "Xojo Instance 2" /MIN XojoWebApp.exe --port=8081

REM Launch Caddy reverse proxy
start "Caddy Proxy" /MIN caddy.exe run --config C:\caddy\Caddyfile</code></pre>



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



<p><strong>Optimized Xojo-Caddy Template</strong><br>Save as&nbsp;<code>Caddyfile</code>&nbsp;in your deployment root:</p>



<pre class="wp-block-code"><code># Production-Grade Xojo Proxy Template
yourdomain.com, www.yourdomain.com {
    # Automated HTTPS
    tls contact@yourdomain.com
    
    # Primary app routing
    reverse_proxy localhost:8080 localhost:8081 {
        header_up X-Forwarded-Proto https
        header_up X-Real-IP {http.request.remote}
    }
    
    # Static content handling
    handle /static/* {
        root * /var/www/static
        file_server
    }
    
    # Security headers
    header {
        Strict-Transport-Security "max-age=31536000"
        Referrer-Policy "strict-origin-when-cross-origin"
    }
}</code></pre>



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



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



<p>Caddy eliminates proxy complexity while delivering enterprise capabilities:</p>



<ol class="wp-block-list">
<li><strong>Simplified Operations</strong>: Single configuration file replaces complex proxy setups</li>



<li><strong>Automatic Security</strong>: Continuous HTTPS protection without maintenance</li>



<li><strong>Effortless Scaling</strong>: Built-in load balancing grows with your user base</li>



<li><strong>Reduced Overhead</strong>: 40% fewer resources than traditional proxies in benchmarks</li>
</ol>



<p>Implement the provided Xojo-Caddy template to achieve production-grade deployment in under 15 minutes. Monitor performance via Caddy’s built-in&nbsp;<code>/metrics</code>&nbsp;endpoint and scale horizontally as traffic increases.</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Web Framework Updates in 2025r2</title>
		<link>https://blog.xojo.com/2025/07/08/web-framework-updates-in-2025r2/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 18:01:00 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r2]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[WebMapViewer]]></category>
		<category><![CDATA[WebStyles]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14977</guid>

					<description><![CDATA[Featuring WebStyle state support for creating more polished user interfaces, enhanced event handling capabilities, and a collection of bug fixes and utility improvements, 2025r2 continues&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Featuring WebStyle state support for creating more polished user interfaces, enhanced event handling capabilities, and a collection of bug fixes and utility improvements, 2025r2 continues improvements to your Web Application development experience with Xojo.</p>



<h2 class="wp-block-heading"><strong>Added Support for WebStyle States</strong></h2>



<p>Working on Desktop projects is all fun and jokes. You can just change how the whole application looks every time your application users move their mouse one pixel to the left. Latency? Who cares!</p>



<p>In order to achieve the same results, WebStyle has been improved to support states. Hover, Pressed and Visited.</p>



<ul class="wp-block-list">
<li><strong>WebStyle.Hover</strong><br>This is the style that will be applied when the mouse is over the element</li>



<li><strong>WebStyle.Pressed</strong><br>This is the style that will be applied when the user is pressing a mouse button in the element</li>



<li><strong>WebStyle.Visited</strong><br>This style can be used with WebLink instances. Used to let the user know the browser has visited that link in the past</li>
</ul>



<p>Consider the following WebContainer:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="686" src="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.31.08-1024x686.png" alt="" class="wp-image-14978" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.31.08-1024x686.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.31.08-300x201.png 300w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.31.08-768x514.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.31.08-1536x1029.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.31.08-2048x1371.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>In this case, it&#8217;s just a container with a WebLabel inside.</p>



<p>The Opening event contains the following code:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="686" src="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.34.34-1024x686.png" alt="" class="wp-image-14979" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.34.34-1024x686.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.34.34-300x201.png 300w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.34.34-768x514.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.34.34-1536x1029.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.34.34-2048x1371.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Please note I&#8217;m using named colors. You can read more about named colors in <a href="https://blog.xojo.com/2024/10/01/introducing-named-color-and-css-classes-in-xojo-web/" data-type="link" data-id="https://blog.xojo.com/2024/10/01/introducing-named-color-and-css-classes-in-xojo-web/">Introducing Named Color and CSS Classes in Xojo Web</a>. If you try using another Bootstrap theme, the same code will use the new color palette without modifications.</p>



<p>Here is the result:</p>



<figure class="wp-block-video aligncenter"><video height="1044" style="aspect-ratio: 1392 / 1044;" width="1392" controls src="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-10.32.14.mp4.mp4"></video></figure>



<p>Combined with <code>WebStyle.AddTransition</code>, it opens the gates for more interesting GUIs. Let&#8217;s add some transitions to our code:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="686" src="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.41.12-1024x686.png" alt="" class="wp-image-14981" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.41.12-1024x686.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.41.12-300x201.png 300w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.41.12-768x514.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.41.12-1536x1029.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.41.12-2048x1371.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Let&#8217;s try the project again:</p>



<figure class="wp-block-video"><video height="1044" style="aspect-ratio: 1392 / 1044;" width="1392" controls src="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-10.41.58.mp4.mp4"></video></figure>



<p>Neat! Let&#8217;s go crazy for a second with more complex effects:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="686" src="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.57.15-1024x686.png" alt="" class="wp-image-14983" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.57.15-1024x686.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.57.15-300x201.png 300w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.57.15-768x514.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.57.15-1536x1029.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-10.57.15-2048x1371.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The result:</p>



<figure class="wp-block-video"><video height="1044" style="aspect-ratio: 1392 / 1044;" width="1392" controls src="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-10.57.58.mp4.mp4"></video></figure>



<p>You should definitely avoid going that crazy, this is just to show the possibilities. As Dr. Ian Malcolm said &#8230; <em>&#8220;Your scientists were so preoccupied with whether or not they could, they didn&#8217;t stop to think if they should.&#8221;</em></p>



<h2 class="wp-block-heading"><strong>WebContainer.Pressed</strong></h2>



<p>Speaking about pressing on things, WebContainer.Pressed event is now available, so you don&#8217;t need to place a WebLabel or a WebContainer on top just to capture that event anymore. The event comes with some coordinates, just in case you need them.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="686" src="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-11.05.54-1024x686.png" alt="" class="wp-image-14985" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-11.05.54-1024x686.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-11.05.54-300x201.png 300w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-11.05.54-768x514.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-11.05.54-1536x1029.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/06/Captura-de-pantalla-2025-06-17-a-las-11.05.54-2048x1371.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The result:</p>



<figure class="wp-block-video"><video height="1044" style="aspect-ratio: 1392 / 1044;" width="1392" controls src="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-11.05.36.mp4.mp4"></video></figure>



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



<p><strong>WebToolbar.Resized</strong></p>



<p>Trying to tweak your design for different screen sizes? If WebToolbar&#8217;s automated behavior is not enough, you can implement the new WebToolbar.Resized event and adapt the contents. This is useful when you are reusing the same WebToolbar subclass in multiple WebPages. You will be able to place this code in just one place.</p>



<p><strong>Exporting maps with WebMapViewer</strong></p>



<p>Same as with MobileMapViewer. You can now use WebMapViewer.ToPicture method to export the current map. Like WebChart.ToPicture, due to the asynchronous nature of Web projects, the picture will be available in the new WebMapViewer.RequestedPicture event.</p>



<p><strong>Updated DataTables</strong></p>



<p>Last, but not least, DataTables has been upgraded from v1.13.4 to v2.2.2.</p>



<h2 class="wp-block-heading"><strong>That&#8217;s (not) all!</strong></h2>



<p>As always, please make sure to check the <a href="https://documentation.xojo.com/versions/2025r2/resources/release_notes/2025r2.html">release notes</a> for a detailed list of new features and bug fixes. The Web framework is built on top of Xojo, new global features or bug fixes also applies to Web, including improvements to Console projects. Xojo Web is &#8220;just&#8221; a big Console project.</p>



<p>Thank you everyone for reporting, testing beta builds and giving us feedback.</p>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-10.32.14.mp4.mp4" length="143729" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-10.41.58.mp4.mp4" length="212247" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-10.57.58.mp4.mp4" length="814128" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/06/Grabacion-de-pantalla-2025-06-17-a-las-11.05.36.mp4.mp4" length="321178" type="video/mp4" />

			</item>
		<item>
		<title>Writing Drawing Code for Android, Desktop, iOS and Web</title>
		<link>https://blog.xojo.com/2025/04/21/writing-drawing-code-for-android-desktop-ios-and-web/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Mon, 21 Apr 2025 19:28:10 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Variants]]></category>
		<category><![CDATA[WebGraphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14826</guid>

					<description><![CDATA[When writing code it&#8217;s always a good idea to be thinking about the future. Today you are creating a desktop project but tomorrow you might&#8230;]]></description>
										<content:encoded><![CDATA[
<p>When writing code it&#8217;s always a good idea to be thinking about the future. Today you are creating a desktop project but tomorrow you might need to create an Android or iOS project. That code you&#8217;re writing might be code you could use for another project for another platform. </p>



<p>For the most part, writing drawing code will <em>just work</em> because you use Xojo&#8217;s <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics" target="_blank" rel="noreferrer noopener">Graphics</a> class for Android, Desktop and iOS projects. Web projects, however, don&#8217;t use the Graphics class. The <a href="https://documentation.xojo.com/api/user_interface/web/webcanvas.html#description" target="_blank" rel="noreferrer noopener">WebCanvas</a> control&#8217;s <a href="https://documentation.xojo.com/api/user_interface/web/webcanvas.html#webcanvas-paint" target="_blank" rel="noreferrer noopener">Paint</a> event is passed a <a href="https://documentation.xojo.com/api/graphics/webgraphics.html" target="_blank" rel="noreferrer noopener">WebGraphics</a> object. While the Graphics and WebGraphics classes have a lot in common, sharing many of the same methods with the same parameters, they are two distinctly different classes from the perspective of the Xojo compiler. That means that while the code you write will look almost identical, you still have to use a Graphics object for Android, Desktop and iOS projects and a WebGraphics object for Web projects. </p>



<p>Your instinct might be to simply write the code for one and then copy it to the other projects, changing Graphics to WebGraphics for Web projects. This will of course work, but then you have to remember to do this copy/paste/change operation every time you update your code. That&#8217;s not ideal.</p>



<h2 class="wp-block-heading">Graphics vs. WebGraphics</h2>



<p>With Xojo, the code can be written in such a way as to automatically handle the difference between Graphics/WebGraphics. Most often your graphics methods will be called from something that provides a Graphics or WebGraphics object for you to draw into such as a Canvas control&#8217;s Paint event. From there your code will call your methods that do the drawing. The problem is that your methods can&#8217;t use a Graphics or a WebGraphics type as a parameter because Graphics is not going to work for your Web projects and WebGraphics doesn&#8217;t exist in any framework except the Web framework. Thus using it anywhere else will result in a compiler error.</p>



<h3 class="wp-block-heading">Using a Variant</h3>



<p>Getting around this limitation is, fortunately, quite easy. Instead of using Graphics or WebGraphics as a parameter type, you use <a href="https://documentation.xojo.com/api/data_types/variant.html" target="_blank" rel="noreferrer noopener">Variant</a>. A Variant can hold any type of data from Strings to Integers, to Graphics to WebGraphics and more.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="560" height="466" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x.png" alt="" class="wp-image-14827" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x.png 560w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x-300x250.png 300w" sizes="auto, (max-width: 560px) 100vw, 560px" /></figure>



<p>Once your drawing method gets the Variant though, it can&#8217;t use it to draw. It can only use a Graphics or WebGraphics objects. The trick is to then copy it into a Graphics or WebGraphics class variable:</p>



<pre class="wp-block-code"><code><code>Var g As Graphics = context</code></code></pre>



<p>or</p>



<pre class="wp-block-code"><code><code>Var g As WebGraphics = context</code></code></pre>



<p>The problem you now face, as mentioned earlier, is that WebGraphics only exists in Web projects. That means you have to write your code in such a way that you will declare the variable g as a Graphics object in Android, Desktop and iOS projects and as a WebGraphics object in Web projects. This can be achieved via conditional compilation. This is a simple technique that tells the Xojo compiler to only compile code into your app if conditions you specify are met. In this case, if you&#8217;re targeting Desktop or Mobile, it should compile in the line that uses the Graphics type, and if you are targeting a Web app, the line that uses WebGraphics. To conditionally compile, you just need to add that conditional code around these two lines:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="wp-block-code"><code>#If TargetDesktop Or TargetMobile Then
   Var g As Graphics = context
#EndIf

#If TargetWeb Then
   Var g As WebGraphics = context
#EndIf</code></pre>
</div></div>
</div></div>



<p>Since a project must be only one of the above types, when you run or build your project, the appropriate line of code will be compiled in. From there, you now have a variable (g) of the right type can use this to draw whatever you like. For example, there are four identical example projects (one for each project type) that show off this technique. They can be found in the Xojo IDE by choosing File > New Project, clicking on Examples, choosing the Graphics folder in the list and then the Cross-Platform Drawing folder. The examples all draw a checkerboard that looks like this:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="912" height="916" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x.png" alt="" class="wp-image-14828" style="width:315px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x.png 912w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-300x300.png 300w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-150x150.png 150w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-768x771.png 768w" sizes="auto, (max-width: 912px) 100vw, 912px" /></figure>
</div>


<p>They all contain the an identical Checkerboard class that handles the drawing. This class has DrawBorder and DrawCheckers methods that both take a Variant as a parameter. In each project is a Canvas control whose Paint event calls these methods:</p>



<pre class="wp-block-code"><code>Var cb As New Checkerboard
cb.DrawBoard(g)
cb.DrawCheckers(g)</code></pre>



<p>The full DrawBoard method looks like this:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="wp-block-code"><code>#If TargetDesktop Or TargetMobile Then
  Var g As Graphics = context
#EndIf

#If TargetWeb Then
  Var g As WebGraphics = context
#EndIf 

Var boxSize As Integer = Min(g.Width/8, g.Height/8) 'The size of the box
'Draw the rows
For y As Integer = 0 To 7
  For x As Integer = 0 To 7
    'Switch colors for each box in the row
    If g.DrawingColor = Color.Black Then
      g.DrawingColor = Color.White
    Else
      g.DrawingColor = Color.Black
    End If
    'Draw a box
    g.FillRectangle(x * boxSize, y * boxSize, boxSize, boxSize)
  Next
  'Switch colors again for the beginning of the next row
  If g.DrawingColor = Color.Black Then
    g.DrawingColor = Color.White
  Else
    g.DrawingColor = Color.Black
  End If
Next</code></pre>
</div></div>



<p>In the example projects, check out the DrawCheckers method as well. It uses the same technique. What is great about this is that this class can be copied into any Android, Desktop, iOS or Web project and it will indeed <em>just work</em>.</p>



<h3 class="wp-block-heading">Checking Out the Examples</h3>



<p>There are four example projects (one for each project type &#8211; Android, Desktop, iOS and Web) that demonstrate the technique explained here. You can find them in the Xojo IDE by choosing File > New Project, clicking on Examples, choosing the Graphics folder in the list and then the Cross-Platform Drawing folder.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Building a Web Kanban Board GUI with Drag and Drop Support</title>
		<link>https://blog.xojo.com/2025/03/25/building-a-web-kanban-board-gui-with-drag-drop-support/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:32:34 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Drag and Drop]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14651</guid>

					<description><![CDATA[Imagine a sleek, interactive Kanban board right in your browser: Columns labeled &#8220;To Do,&#8221; &#8220;In Progress,&#8221; and &#8220;Done,&#8221; each populated with cards representing tasks. With&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Imagine a sleek, interactive Kanban board right in your browser: Columns labeled &#8220;To Do,&#8221; &#8220;In Progress,&#8221; and &#8220;Done,&#8221; each populated with cards representing tasks. With Xojo’s new drag and drop support for web projects, you can grab a card with your mouse, drag it to another column to update its status, or even reorder it within the same column to prioritize it.</p>



<h2 class="wp-block-heading"><strong>The End Result</strong></h2>



<figure class="wp-block-video aligncenter"><video height="1410" style="aspect-ratio: 1854 / 1410;" width="1854" controls src="https://blog.xojo.com/wp-content/uploads/2025/03/kanban-board-demo.mp4"></video><figcaption class="wp-element-caption">Kanban board demo</figcaption></figure>



<p>The latest drag and drop example has a functional GUI that looks professional and feels intuitive. All without writing a single line of JavaScript (we will enhance it a bit with some CSS, though).</p>



<p>Please note this is a sample project created to explore drag and drop, not a full featured Kanban board. I&#8217;ll omit on purpose things like persistence. The complete project can be found in the Examples section of the IDE, under <strong>Platforms > Web</strong>.</p>



<p>Let’s walk through how to make it happen.</p>



<h2 class="wp-block-heading"><strong>Creating the Required Components</strong></h2>



<p>First, we need to define the building blocks of our Kanban board. In Xojo, WebContainers are perfect for modularizing reusable UI elements. Here’s what we’ll create:</p>



<ul class="wp-block-list">
<li><strong>KanbanCard</strong><br>A WebContainer to represent each task card. It’ll have a simple label for the task name (e.g., &#8220;Write blog post&#8221;) and maybe a colored border or handle to indicate it’s draggable. Add a WebLabel for the text and set its properties in the Inspector to make it visually distinct.</li>



<li><strong>KanbanCardContainer</strong><br>Another WebContainer to act as a column. It’ll hold multiple KanbanCard Containers and serve as both a drag source (where cards come from) and a drop target (where cards land). Include a WebLabel at the top for the column title (e.g., &#8220;To Do&#8221;) and a rectangular area below it to house the cards.</li>



<li><strong>Main Page</strong><br>A WebPage to host everything. This is where we’ll arrange our columns side by side.</li>
</ul>



<p>In the Xojo IDE, drag a WebContainer onto your project for the Card, another for the Column, and set up three instances of the Column Container on the main WebPage (&#8220;To Do,&#8221; &#8220;In Progress,&#8221; &#8220;Done&#8221;).</p>



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


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="807" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-15.50.08-1024x807.png" alt="" class="wp-image-14653" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-15.50.08-1024x807.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-15.50.08-300x236.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-15.50.08-768x605.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-15.50.08.png 1190w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">The KanbanCard custom control</figcaption></figure>
</div>


<p>This component will be pretty easy to build. It is basically a WebRectangle with a WebLabel that we will use for the Title. To make it easier to update, I&#8217;ve added a Title Computed Property that will update the TitleLabel if needed.</p>



<p>For the background WebRectangle, we will use the following ColorGroup. Please notice Xojo added support for Named colors, that will rely on the current Bootstrap theme, supporting Dark Mode:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="807" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-17.44.17-1024x807.png" alt="" class="wp-image-14654" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-17.44.17-1024x807.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-17.44.17-300x236.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-17.44.17-768x605.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-06-a-las-17.44.17.png 1190w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Adding a ColorGroup using a Bootstrap Named Color</figcaption></figure>
</div>


<p>As you can see, BackgroundRectangle and TitleLabel controls are implementing the Opening event. This is just to set the mouse cursor that will be shown when we hover:</p>



<pre class="wp-block-code xojo"><code>Me.Style.Cursor = WebStyle.Cursors.Move</code></pre>



<p>The container itself is also implementing the Opening event. This is to make this control draggable, using the following line of code:</p>



<pre class="wp-block-code xojo"><code>AllowTextDrag(WebDragItem.DragActionTypes.Move)</code></pre>



<p>Any descendant of the WebUIControl class is draggable. And yes, that includes custom controls created with the Web SDK.</p>



<p>For the WebDragItem.DragActionTypes Enumeration, you can choose one these options:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="324" height="386" src="https://blog.xojo.com/wp-content/uploads/2025/03/1-CopyAndLink.png" alt="" class="wp-image-14655" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/1-CopyAndLink.png 324w, https://blog.xojo.com/wp-content/uploads/2025/03/1-CopyAndLink-252x300.png 252w" sizes="auto, (max-width: 324px) 100vw, 324px" /><figcaption class="wp-element-caption">The WebDragItem.DragActionTypes Enumeration</figcaption></figure>
</div>


<p>In this case we will only be allowed to &#8220;Move&#8221; a card from one place to another.</p>



<p>There are cases where it makes sense to support multiple drag action types. In your operating system&#8217;s file browser, when you drag and drop files and folders, you can change between Move, Link or Copy by using Keyboard shortcut combinations. Depending on the drag action type, the element will be moved, a symbolic link will be created, or it will be copied, respectively.</p>



<p>Normally you will implement just Move or Copy, but keep in mind it&#8217;s possible to have more (at the cost of increasing the learning curve of your application for your users)</p>



<p>Allowing something to be dragged is the first of two steps. You also need a place to drop these items into.</p>



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



<p>This container will be more elaborate, but should be easy to follow. Let&#8217;s see how it works at runtime, with some annotations:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="895" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/03/WebLabel-895x1024.png" alt="" class="wp-image-14656" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/WebLabel-895x1024.png 895w, https://blog.xojo.com/wp-content/uploads/2025/03/WebLabel-262x300.png 262w, https://blog.xojo.com/wp-content/uploads/2025/03/WebLabel-768x879.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/WebLabel.png 1071w" sizes="auto, (max-width: 895px) 100vw, 895px" /><figcaption class="wp-element-caption">Combined controls to create the KanbanCardContainer</figcaption></figure>
</div>


<p>The WebLabel we used for the Title and the WebButton used for adding new cards are positioned manually in the IDE designer. Same as the invisible WebRectangle holding the KanbanCard items and the KanbanAddCard custom button.</p>



<p>But instead of placing our cards manually, we&#8217;ll take advantage of the browser&#8217;s capacity for doing this job for us. We just want to add them dynamically at runtime and let the browser stack them vertically, automatically. We also want the browser to display a scrollbar if the columns have several cards.</p>



<p>Here is the code we will add to the WebRectangle:</p>



<pre class="wp-block-code"><code>// Let the framework know we want to let the
// browser place the items automatically
Me.LayoutType = LayoutTypes.Flex

// This style will ensure cards won't be
// placed horizontally by the browser
Me.Style.Value("flex-direction") = "wrap"

// If there are more cards than available
// space, this style will allow the user
// to scroll
Me.Style.Value("overflow") = "auto"</code></pre>



<p>Let&#8217;s add some methods to add and remove cards at runtime.</p>



<ul class="wp-block-list">
<li>AddCardWithTitle(title As String)</li>



<li>AddCardWithTitleAt(title As String, index As Integer)</li>



<li>RemoveCardAt</li>
</ul>



<h2 class="wp-block-heading"><strong>Moving Cards Between Columns</strong></h2>



<p>Here’s where Xojo’s drag and drop shines. Each Card Container needs to be draggable and each Column Container needs to accept dropped cards. In Xojo:</p>



<ol class="wp-block-list">
<li><strong>Make Cards Draggable</strong>: Open the KanbanListCard in the IDE and implement the Opening event. Enter this code:<br><code>AllowTextDrag(WebDragItem.DragActionTypes.Move)</code></li>



<li><strong>Accept Card Drops:</strong> Open the KanbanCardContainer and implement the Opening event. This is the code we need in order to accept drops:<br><code>AcceptTextDrop(WebDragItem.DragActionTypes.Move)</code></li>



<li><strong>Remove from Source</strong>: To move (not copy) the card, in the source Column’s DragEnd event, remove the dragged card from its original parent after a successful drop.</li>
</ol>



<p>With this, you can drag a card from &#8220;To Do&#8221; to &#8220;In Progress,&#8221; and it’ll visually jump columns. Xojo handles the heavy lifting. No JavaScript or DOM manipulation needed!</p>



<h2 class="wp-block-heading"><strong>The Hard Part: Reordering Cards</strong></h2>



<p>Reordering cards within a column, or dropping a card into another column in a specific position is trickier. You need to detect where the card lands among its siblings and adjust their positions. Xojo’s drag and drop doesn’t natively sort UI elements, so we’ll simulate it.</p>



<p>There are several ways to achieve this, let&#8217;s explore some options.</p>



<p>One would be to deal with X/Y coordinates. Once you drop a card, you could take a look to see where the card landed, compare the coordinates with the other cards and reorder them accordingly. In desktop and mobile projects this could be a valid solution. In web projects, dealing with specific coordinates might work, but there are more accurate and easier solutions.</p>



<p>The second way could be good enough in most cases. Cards could also accept drops so, if you drop one card on another, we just have to put the card being dropped in the position where it&#8217;s being dropped, and push down the rest of the stack. This way you won&#8217;t need to scratch your head and deal with screen coordinates or control dimensions. The end result will be based on this idea.</p>



<p>But what should we do to generate the gap between Cards? Maybe you can create a transparent Container that also accept Card drops, to simulate the gap between cards.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/03/KanbanCardContainer-1024x1024.png" alt="" class="wp-image-14657" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/KanbanCardContainer-1024x1024.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/KanbanCardContainer-300x300.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/KanbanCardContainer-150x150.png 150w, https://blog.xojo.com/wp-content/uploads/2025/03/KanbanCardContainer-768x768.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/KanbanCardContainer.png 1158w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">One way of achieving sorting, that we are not using in the sample project</figcaption></figure>
</div>


<p>This would work for you, and I honestly recommend you to give it a try, it&#8217;s super easy to implement and it will just work. If you don&#8217;t want to explore the CSS rabbit hole, that&#8217;s fine, this can be your bus stop.</p>



<p>Two downsides:</p>



<ul class="wp-block-list">
<li>You won&#8217;t have animations</li>



<li>You will double the amount of controls on screen (performance may suffer)</li>
</ul>



<p>I went in another direction though. Using some CSS, you can add and modify margins on the fly, with neat transitions. In my sample project, the margin between cards is managed by the `margin-top` CSS style.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="274" height="444" src="https://blog.xojo.com/wp-content/uploads/2025/03/In-Progress.png" alt="" class="wp-image-14658" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/In-Progress.png 274w, https://blog.xojo.com/wp-content/uploads/2025/03/In-Progress-185x300.png 185w" sizes="auto, (max-width: 274px) 100vw, 274px" /><figcaption class="wp-element-caption">Top margin added to KanbanCardContainer, using CSS styles</figcaption></figure>
</div>


<p>And here is where the Xojo Framework helps. To make styling easier, it adds a CSS class to the element being dragged and also to the element where the mouse is over, when it&#8217;s accepting a drop.</p>



<p><code>dragging</code> &#8211; The HTML element being dragged will have this property<br><code>dragover</code> &#8211; The HTML element under the other element being dragged</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="815" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.15.44-1024x815.png" alt="" class="wp-image-14659" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.15.44-1024x815.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.15.44-300x239.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.15.44-768x611.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.15.44-1536x1223.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.15.44-2048x1630.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Some CSS Classes added by the Xojo Web Framework at runtime, to help styling Drag and Drop</figcaption></figure>
</div>


<p>In this case, the &#8220;Bar&#8221; card will receive the dragging CSS class, while &#8220;Test #2&#8221; will receive the dragover CSS class, while the &#8220;Bar&#8221; car is above.</p>



<p>I&#8217;ve added some transparency to elements with the dragging class. As you can see in the screenshot, the &#8220;Bar&#8221; Card opacity is set to 30%.</p>



<p>For dragover class, I&#8217;ve added some margin and transitions. If you drag something into a card, the top margin will grow, simulating it&#8217;s making room for the card you are about to drop.</p>



<p>Here is how the HTML Header section of the sample project looks like. It isn&#8217;t too much code, but it does uses some somewhat advanced CSS tricks:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="807" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.29.14-1024x807.png" alt="" class="wp-image-14660" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.29.14-1024x807.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.29.14-300x236.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.29.14-768x605.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.29.14-1536x1211.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.29.14-2048x1614.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Custom CSS added to App &gt; HTML Header</figcaption></figure>
</div>


<p>This approach keeps cards neatly stacked and sortable. It’s the &#8220;hard part&#8221; not because you will have to write a lot of code, but because you&#8217;ll actually have to think a solution that won&#8217;t require roundtrips between the browser and the server. Xojo’s event system makes it manageable without JavaScript, and with some CSS, the result will be great.</p>



<h2 class="wp-block-heading"><strong>Some CSS Enhancements</strong></h2>



<p>In some cases I&#8217;m using shadows and border radius using the Bootstrap&#8217;s CSS classes.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="807" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.44.21-1024x807.png" alt="" class="wp-image-14661" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.44.21-1024x807.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.44.21-300x236.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.44.21-768x605.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.44.21-1536x1211.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-09-a-las-18.44.21-2048x1614.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Bootstrap CSS Classes to make the card be rounded and have a subtle shadow</figcaption></figure>
</div>


<p>As you can see, I&#8217;m using rounded-2 for the border radius, and shadow-sm to easily add a shadow to the cards.</p>



<p>You can read more about this in the following blog post:<br><a href="https://blog.xojo.com/2024/10/01/introducing-named-color-and-css-classes-in-xojo-web/" data-type="post" data-id="13668">Introducing Named Color and CSS Classes in Xojo Web</a></p>



<p>There is a related sample project you might want to check:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="822" src="https://blog.xojo.com/wp-content/uploads/2025/03/Platform-1024x822.png" alt="" class="wp-image-14662" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Platform-1024x822.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Platform-300x241.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Platform-768x616.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Platform-1536x1233.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/Platform.png 1762w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Xojo Web Examples</figcaption></figure>
</div>


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



<p>This has been a fun experiment to explore the Xojo Web drag and drop feature. Give the sample project a try and explore each control to see how it&#8217;s been created. I can&#8217;t recommend enough that you try to build it from scratch (and ask in the forum if you get stuck!)</p>



<p>We can&#8217;t wait to hear about how you plan to introduce drag and drop into your projects. Don&#8217;t be shy and create a forum thread to show what you have built, or what you are working on.</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/03/kanban-board-demo.mp4" length="710061" type="video/mp4" />

			</item>
		<item>
		<title>Xojo Web Evolves: What’s Here in 2025r1?</title>
		<link>https://blog.xojo.com/2025/03/25/xojo-web-evolves-whats-here-in-2025r1/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:31:35 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14678</guid>

					<description><![CDATA[What happens when Xojo Web adds drag and drop support, supercharges WebListBox, and packs in 40+ changes? Let’s find out! Drag and Drop Support The&#8230;]]></description>
										<content:encoded><![CDATA[
<p>What happens when Xojo Web adds drag and drop support, supercharges WebListBox, and packs in 40+ changes? Let’s find out!</p>



<h2 class="wp-block-heading"><strong>Drag and Drop Support</strong></h2>



<p>The biggest thing this time is that we&#8217;ve added general drag and drop support for web. From now on, any visual control can be dragged or accept drops.. That includes controls created using the Web SDK, allowing you (and third-party developers!) to increase the user experience on your web projects.</p>



<p>Now, imagine new ways of updating a Database application. For example, creating a &#8220;Form Builder&#8221;, a full &#8220;Website Builder&#8221; or even a &#8220;Database Schema&#8221; web application where the user can drag elements from a library and drop them into the editor. Are you scheduling posts on social networks using a WebDatePicker? What about using a calendar view with drag and drop support?</p>



<p>We&#8217;ve included a drag and drop Kanban board example. Take a look at <a href="https://blog.xojo.com/2025/03/25/building-a-web-kanban-board-gui-with-drag-drop-support/">the blog post</a> to learn more about it.</p>



<figure class="wp-block-video"><video height="1410" style="aspect-ratio: 1854 / 1410;" width="1854" controls src="https://blog.xojo.com/wp-content/uploads/2025/03/kanban-board-demo-1.mp4"></video></figure>



<p>How cool is that?</p>



<p>While drag and drop can make your app easier to work with for some users, it can also be an accessibility barrier for other users. Just remember to offer an alternative way for interacting with your application. In a full featured Kanban app, for example, the user should still be able to change the status of a task from the task details screen, using a regular WebPopupMenu (or any other accessible method)</p>



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



<p>Speaking of dragging things, WebListBox also now supports reordering rows using the mouse. Just enable the new Allow Row Reordering property (which is Off by default) and you are all set.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="676" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.49.42-1024x676.png" alt="" class="wp-image-14680" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.49.42-1024x676.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.49.42-300x198.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.49.42-768x507.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.49.42-1536x1014.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.49.42-2048x1352.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This can also be set programmatically at runtime with AllowRowReordering. Once the user finishes a reorder, the RowsReordered event is called, allowing you to persist the changes in your database, for example.</p>



<figure class="wp-block-video"><video height="1034" style="aspect-ratio: 1320 / 1034;" width="1320" controls src="https://blog.xojo.com/wp-content/uploads/2025/03/Grabacion-de-pantalla-2025-03-13-a-las-12.06.45.mp4.mp4"></video></figure>



<p>Another requested feature was to allow users to perform inline edits. <a href="https://documentation.xojo.com/api/user_interface/web/weblistbox.html#">WebListBox</a> received some new methods and events to handle this:</p>



<ul class="wp-block-list">
<li><strong>ColumnTypeAt:</strong> To make a whole column editable</li>



<li><strong>CellTypeAt:</strong> To override the ColumnTypeAt on specific cells</li>



<li><strong>EditCellAt:</strong> A method you can use to begin the edit on specific cells</li>



<li><strong>CellAction Event:</strong> Allowing you to persist the changes made by the user</li>
</ul>



<p>This is also supported when using a WebDataSource.</p>



<p>And not only are TextField and TextArea supported, CheckBox is also part of the WebListBox.CellTypes enumeration, to match what DesktopListBox supports:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="794" src="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.52.16-1024x794.png" alt="" class="wp-image-14682" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.52.16-1024x794.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.52.16-300x233.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.52.16-768x596.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/Captura-de-pantalla-2025-03-13-a-las-11.52.16.png 1318w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Last, but not least, we&#8217;ve decided to split CellTextAt into two different methods. Until now, you could get and set the caption of a cell using CellTextAt, but also a WebListBoxCellRenderer. This could cause trouble because a Variant was being returned, that could be either a String or a WebListBoxCellRenderer so, when not being used carefully, it could raise IllegalCastException at runtime.</p>



<p>From now on, CellTextAt will only support String. If you want to get or set a cell renderer, you will have to use CellRendererAt instead. This makes the API more obvious.</p>



<p>If you were using CellTextAt for getting and setting cell renderers, you will need to update your code to use CellRendererAt instead.</p>



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



<p>This release empowers Xojo Web projects to meet more user needs, no JavaScript required. Drag and drop finally joins the party, filling a critical gap from the old Web 1 framework.</p>



<p>Be sure to dig into the <a href="https://documentation.xojo.com/resources/release_notes/2025r1.html#">release notes</a>, as 2025r1 packs over 40 changes for the web target alone.</p>



<p>I’d love to hear how you’re weaving these updates into your projects! Drop some screenshots or screen recordings in a new forum thread or shoot me a private message if you prefer.</p>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/03/kanban-board-demo-1.mp4" length="710061" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/03/Grabacion-de-pantalla-2025-03-13-a-las-12.06.45.mp4.mp4" length="378839" type="video/mp4" />

			</item>
		<item>
		<title>A Complete Dockerfile for Web Apps</title>
		<link>https://blog.xojo.com/2025/03/19/a-complete-dockerfile-for-web-apps/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Wed, 19 Mar 2025 15:19:48 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14708</guid>

					<description><![CDATA[For a comprehensive guide on deploying Xojo web apps to any server, please refer to the video tutorial available at: https://youtu.be/ARr7d6Z6CRY I also recommend reading&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For a comprehensive guide on deploying Xojo web apps to any server, please refer to the video tutorial available at: <a href="https://youtu.be/ARr7d6Z6CRY" target="_blank" rel="noreferrer noopener">https://youtu.be/ARr7d6Z6CRY</a></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Complete Guide to Dockerize &amp; Deploy your Web Apps" width="500" height="281" src="https://www.youtube.com/embed/ARr7d6Z6CRY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<ul class="wp-block-list">
<li>The Dockerfile below should be placed in the same directory as your Xojo project</li>



<li>Remember to modify the&nbsp;<code>WEBAPP_NAME</code>&nbsp;variable on line 33 to match the name of your project</li>



<li>Feel free to customize this Dockerfile to suit your specific needs. We encourage you to share your modifications and experiences in the Xojo <a href="https://forum.xojo.com/" data-type="link" data-id="https://forum.xojo.com/" target="_blank" rel="noreferrer noopener">forum</a></li>
</ul>



<pre class="wp-block-code"><code># Step-by-Step Instructions for Building, Saving, and Running the Image:
# 1. Build the Docker image:
#    "docker build -t hellodocker-image ."
#    This creates a Docker image named "hellodocker-image" based on this Dockerfile.
#
# 2. Save the Docker image to a tar file:
#    "docker save -o hellodocker-image.tar hellodocker-image"
#    This saves the "hellodocker-image" to a file named "hellodocker-image.tar".
#    You can use this file to transfer the image to another server.
#
# 3. Upload the .tar file to the remote server.
#    After transferring the tar file, follow these steps on the remote server:
#
#    3.1 Load the Docker image:
#        "docker load -i hellodocker-image.tar"
#        This imports the image into the Docker environment on the server.
#
#    3.2 Run a container from the image:
#        "docker run -d --name hellodocker-container --restart always -p 7000:80 hellodocker-image"
#        This creates and starts a container named "hellodocker-container" that:
#        - Restarts automatically if it stops (via `--restart always`).
#        - Maps port 80 inside the container to port 7000 on the host machine.
#
#    3.3 Verify the web app is running:
#        Open a web browser and navigate to http://server-ip:7000
#        Replace "server-ip" with the IP address of your remote server.
#
# Complete video guide at: https://youtu.be/ARr7d6Z6CRY

# Use Ubuntu 22.04 as the base image for the container.
FROM ubuntu:22.04

# Define the name of the Xojo web app executable.
# This should match the exact name of your compiled Xojo web app (case-sensitive).
ENV WEBAPP_NAME=HelloDocker

# Prevent interactive prompts during the installation of dependencies.
ENV DEBIAN_FRONTEND=noninteractive

# Install required system libraries for the Xojo web app to run, and purge unnecessary software (PHP, Python, Apache)
RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    curl \
    ca-certificates \
    libunwind8 \
    libsoup2.4 \
    libpango-1.0 \
    libicu70 \
    libglib2.0 \
    libgtk-3-0 \
    &amp;&amp; apt-get purge -y php* python3* apache2* libapache2-mod-php* \
    &amp;&amp; apt-get autoremove -y \
    &amp;&amp; apt-get clean \
    &amp;&amp; rm -rf /var/lib/apt/lists/*

RUN useradd --create-home ${WEBAPP_NAME}

# Set the working directory inside the container.
# This is where the web app files will be located.
WORKDIR /${WEBAPP_NAME}

# Copy the built Xojo web app from the build context into the container.
# Remember, this Dockerfile must be placed in the same folder as the Xojo project.
COPY &#91;"Builds - ${WEBAPP_NAME}/Linux 64 bit/${WEBAPP_NAME}", "."]

# Change ownership of the application files to the non-root user
RUN chown -R ${WEBAPP_NAME}:${WEBAPP_NAME} /${WEBAPP_NAME}

# Ensure the main web app executable has permission to run
RUN chmod +x ${WEBAPP_NAME}

# Create a directory for persistent data storage.
# Ensure the data directory is owned by the non-root user.
RUN mkdir -p /home/${WEBAPP_NAME}/data &amp;&amp; chown -R ${WEBAPP_NAME}:${WEBAPP_NAME} /home/${WEBAPP_NAME}/data

# Define the volume for the container to store data.
# The contents of "/home/${WEBAPP_NAME}/data" will persist outside the container.
VOLUME /home/${WEBAPP_NAME}/data

# Switch to the non-root user for security purposes.
# All subsequent instructions (including CMD) will run as this user.
USER ${WEBAPP_NAME}

# Expose port 80 inside the container.
# This allows the web app to listen on port 80, which will be mapped to port 7000
# on the host machine when the container is run.
EXPOSE 80

# Start the Xojo web app when the container runs.
# The app will listen on port 80 inside the container.
CMD &#91;"sh", "-c", "./${WEBAPP_NAME} --port=80"]</code></pre>



<p>I also recommend reading this article for additional details on Xojo and Docker: <a href="https://blog.xojo.com/2021/05/17/running-xojo-web-applications-in-docker/" target="_blank" rel="noreferrer noopener">https://blog.xojo.com/2021/05/17/running-xojo-web-applications-in-docker/</a></p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spotlight On: Tim Dietrich</title>
		<link>https://blog.xojo.com/2025/03/10/spotlight-on-tim-dietrich/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Mon, 10 Mar 2025 16:00:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FileMaker]]></category>
		<category><![CDATA[NetSuite]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14631</guid>

					<description><![CDATA[Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and spread awareness of community resources. If you have an app, a project or a person you want to see featured in Spotlight On,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</a>!</em></p>



<p>I&#8217;ve had the pleasure of working with Tim multiple times over nearly 10 years now. Tim is one of those people who makes a community, he&#8217;s a connector, bringing people into a group and highlighting common ground for the benefit of us all. It&#8217;s not hard to find out what Tim is doing these days, you can read all about it on his blog, watch his videos and webinars and read his Xojo interview series in xDev Magazine. In this month&#8217;s Spotlight On feature, Tim answers questions about his latest, and biggest, project and his ongoing success using Xojo.</p>



<h3 class="wp-block-heading"><strong>Mac, Windows or Linux?</strong></h3>



<p>All three.</p>



<p>I do all of my work on a MacBook Pro. That&#8217;s where I&#8217;m running the Xojo IDE, doing testing, and so on. But I&#8217;m developing apps that also run on Windows and Linux, too. When I&#8217;m developing a Windows app, I usually do my initial testing using a Windows VM running in Parallels. Over the past few years, the amount of Linux projects that I work on has increased significantly. I&#8217;m developing a lot of console apps that run on Linux.</p>



<p>Here&#8217;s something that I discovered about a year ago, and that your readers might find interesting. Xojo apps that are compiled for Linux (Linux x86 64-bit in particular) will run on servers that are running Oracle&#8217;s &#8220;Oracle Linux Server&#8221; operating system. Oracle&#8217;s cloud (which they call &#8220;Oracle Cloud Infrastructure&#8221; or &#8220;OCI&#8221; for short) run that version of Linux, which is similar to Fedora. A lot of companies that are running on NetSuite (which Oracle owns) are &#8220;all in&#8221; with OCI. So the fact that Xojo apps can be compiled to run on OCI servers is a pretty big deal. I think there&#8217;s a lot of opportunity for Xojo developers to meet the demand for custom software coming from companies that are in investing in OCI.</p>



<h3 class="wp-block-heading"><strong>What do you wish more people would ask/talk to you about regarding programming?</strong></h3>



<p>I have a pretty popular blog, and I do get a lot of technical questions from readers. Occasionally, I get questions like &#8220;How can I break into the NetSuite space?&#8221; What they&#8217;re really asking about are strategies for finding opportunities, technical things that they should learn about, and so on. </p>



<p>But it&#8217;s the non-technical things that they don&#8217;t ask about that I think are really important. For example, learning about business in general. Learning about accounting. And if they&#8217;re looking to &#8220;go solo,&#8221; learning how to build authority, stay organized, and so on.</p>



<h3 class="wp-block-heading"><strong>How would you explain your most recent project to a new developer?</strong></h3>



<p>One of the biggest challenges that companies face when they&#8217;re switching from one business system to another is migrating data between the two systems. Some companies think that this is the final step before &#8220;going live&#8221; with the new system &#8211; and it certainly is.</p>



<p>But the reality is that they&#8217;ll likely need to do this data migration several times, especially as they test the new system. In some cases, they&#8217;ll run the two systems in parallel and compare the results of the two systems, to make sure the new system is being implemented correctly.</p>



<p>I&#8217;m currently working on a very large, very complicated NetSuite implementation, and we ran into this need. Using Xojo, I developed an app called the &#8220;Data Bridge&#8221; which we&#8217;re using to sync data between their current system (which was developed using Progress &#8211; https://progress.com) and their NetSuite instance. It takes data that was exported from Progress as pipe-delimited files, parses and validates the data, and then makes API calls to push the data into NetSuite. This is helping us test NetSuite more thoroughly, using current, real data, so that there will be no surprises when we do go live.</p>



<h3 class="wp-block-heading"><strong>What’s next on your “Learn Next” list?</strong></h3>



<p>For the longest time, I&#8217;ve felt that AI &#8211; and especially generative AI &#8211; is overhyped. So I mostly ignored it. Now that the excitement has settled down a bit, I&#8217;ve started to look at AI in a serious way. NetSuite recently made some generative AI APIs available to developers, so I&#8217;ve been experimenting with those. One of the projects that I&#8217;m currently working on involves developing a Xojo-based mobile app that integrates with NetSuite, leveraging the data stored in NetSuite as well as its AI functionality.</p>



<h3 class="wp-block-heading"><strong>What is something that has surprised you about coding in the last 10 years?</strong></h3>



<p>I think that like a lot of developers that have been working professionally for awhile, I was surprised by the popularity of Javascript, and how widespread it&#8217;s used, especially for developing backend Web apps. The other thing that has surprised me is the increasing number of developers that really don&#8217;t want to write code. There seem to be a lot of people that pursue careers in software development simply because they think it&#8217;s a way to &#8220;make big money.&#8221; One of the things that<br>I love about the Xojo community is that most of the Xojo developers that I&#8217;ve talked to seem to find joy in writing code. (You can also see this on the Forum, too.)</p>



<h3 class="wp-block-heading"><strong>Xojo isn’t the only tool in your kit. What is a piece of software more people should know about?</strong></h3>



<p>There are a couple of other development tools that I use and recommend, and that I encourage other Xojo developers to check out.</p>



<p>One is <a href="https://www.jetbrains.com/datagrip/" target="_blank" rel="noreferrer noopener">DataGrip</a> by JetBrains, which I started using about a year ago. DataGrip is a cross- platform database tool that supports a very wide range of relational databases. I use it often in my NetSuite work, especially when I need to explore the schema of the Oracle database that a NetSuite instance is powered by. </p>



<p>Another tool that I recommend is <a href="https://rapidapi.com/" target="_blank" rel="noreferrer noopener">RapidAPI</a> (which was formerly known as &#8220;Paw&#8221;). I&#8217;ve been using RapidAPI since it was first released, and it&#8217;s my API tool of choice. There&#8217;s another API tool called &#8220;Postman&#8221;that is certainly much more popular, but I really prefer RapidAPI. It seems to me to be much more Mac-like. </p>



<p>One more tool that I want to mention &#8211; and this one is brand new &#8211; is called &#8220;<a href="https://apps.apple.com/us/app/framous-screenshot-frames/id6636520519?mt=12" target="_blank" rel="noreferrer noopener">Framous</a>.&#8221; Framous makes it easy to add device frames around screenshots. So you can take a screenshot of an app &#8211; such as one running on your Mac or in a simulator &#8211; and then drop the screenshot into a device frame &#8211; such as a Mac or iPhone. It&#8217;s great for creating images to be used for marketing purposes. The app is available on the Mac App Store.</p>



<h3 class="wp-block-heading"><strong>When did you start using Xojo?</strong></h3>



<p>I started using Xojo in August of 2015 &#8211; nearly 10 years ago!</p>



<h3 class="wp-block-heading"><strong>How did you find Xojo?</strong></h3>



<p>Hal Gumbert encouraged me to check out Xojo, and I&#8217;m so glad that he did. At the time, we were both FileMaker developers. I had grown frustrated with the FileMaker platform and was looking for a new development tool to work with.</p>



<h3 class="wp-block-heading"><strong>What did you first&nbsp;build with Xojo?</strong></h3>



<p>When I first started working with Xojo, I was interested in developing iOS apps &#8211; and Xojo&#8217;s support for the iOS framework had just been released. So the timing was perfect. In fact, then first Xojo license that I purchased was only for iOS. There were two iOS apps that I immediately developed with Xojo. One integrated with FileMaker and the other integrated with Airtable. (At the time, I was serving as Airtable&#8217;s &#8220;Developer Evangelist.&#8221;)</p>



<h3 class="wp-block-heading"><strong>What do you build with it now?&nbsp;</strong></h3>



<p>I now use Xojo to develop all kinds of apps &#8211; desktop, mobile, Web, and console apps &#8211; and for all of the platforms that Xojo supports too (macOS, Windows, Linux, iOS, and Android). When I first started using Xojo, I never would have guessed that someday I&#8217;d be developing so many different types of apps.</p>



<p>It surprises me that out of all of the types of apps that I develop with Xojo, these days it&#8217;s Linux console apps that I&#8217;m developing the most. These apps are primarily used to automate processes involving NetSuite, such as batch file processors, webhook listeners and senders, and more. So essentially I&#8217;m using Xojo &#8211; and console apps especially &#8211; to extend NetSuite&#8217;s capabilities.</p>



<h3 class="wp-block-heading"><strong>What is something you worked on recently that you want to talk about?</strong></h3>



<p>I mentioned a few of my current projects earlier, but two of the more interesting projects that I&#8217;m working on are Suite.js (a JavaScript runtime that’s designed to make NetSuite integration easy) and SuiteBrowser (a Web browser designed specifically for use with NetSuite). Both of those projects might sound like crazy ideas. I mean, what kind of crazy person develops their own web browser?!? But I can tell you, based on the level of interest in them from the NetSuite community, that there&#8217;s a genuine need for both of them.</p>



<h3 class="wp-block-heading"><strong>Do you earn a living with Xojo?&nbsp;</strong></h3>



<p>Absolutely. So much of my work these days &#8211; including my NetSuite work &#8211; involves Xojo. I honestly don&#8217;t know what I&#8217;d do without it.</p>



<p>Also, I want to give a shout out to Christian Schmitz and <a href="https://www.monkeybreadsoftware.de/xojo/">MonkeyBread Software</a>. His Xojo plug-ins have enabled me to work on Xojo projects that I never would have dreamed of working on, including projects that utilize things like MQTT, Phidgets, and more.</p>



<h3 class="wp-block-heading"><strong>Do you use it for your hobbies?&nbsp;</strong></h3>



<p>Yes, I do. My main hobby these days is developing apps that run on Raspberry Pi&#8217;s, and of course, I&#8217;m using Xojo to create them. As a side note, I recently purchased my fifth Raspberry Pi &#8211; a Raspberry Pi 500 &#8211; and I love working with it. It reminds me what it was like to use Macs and PCs &#8220;back in the day.&#8221;</p>



<h3 class="wp-block-heading"><strong>What’s your biggest Xojo success?</strong></h3>



<p>Out of all of the apps that I&#8217;ve developed with Xojo, the one that I use every day is called SuiteTransmit. SuiteTransmit is a desktop app that monitors the files that I&#8217;m working on, detects changes to them, and automatically uploads them to NetSuite. It allows me to develop NetSuite &#8220;SuiteScript&#8221; apps using my preferred IDE (BBEdit). This simple app, which, thanks to Xojo, took only a few hours to develop, has saved me a lot of time. SuiteTransmit is one of my &#8220;secret weapons,&#8221; and I don&#8217;t think I could have, or would have ever even attempted to develop it, without Xojo.</p>



<p>But my biggest &#8220;Xojo success&#8221; doesn&#8217;t involve any one particular app that I&#8217;ve developed with it. Over the years, I&#8217;ve blogged about my Xojo work, and been a guest on several Xojo webinars. Last summer, a company that was looking for help implementing NetSuite stumbled upon my NetSuite / Xojo work, liked what they saw, and reached out to me for help. They&#8217;re now my biggest client, and the biggest client I&#8217;ve had throughout my entire career. And I owe that to Xojo.</p>



<p><em>Thank you to Tim Dietrich for answering questions and sharing his Xojo experience with the community.&nbsp;Learn more about&nbsp;<a href="https://timdietrich.me/">Tim on his blog</a>, find him on <a href="https://www.linkedin.com/in/tim-dietrich/">LinkedIn</a></em> and read his interviews in <a href="https://xdevmag.com/">xDev Magazine</a>.</p>



<p><em>If you have an app, a project or a person you want to see featured in Spotlight On,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</a>!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<ul class="wp-block-list">
<li><a href="https://www.facebook.com/goxojo" target="_blank" rel="noreferrer noopener"></a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Year of Code 2025: March Project, Web Apps</title>
		<link>https://blog.xojo.com/2025/03/05/year-of-code-2025-march-project-web-apps/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Wed, 05 Mar 2025 15:04:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Games]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14588</guid>

					<description><![CDATA[March’s topic is Web Apps and I’m excited to introduce my project: Quiziverse, a complete quiz and trivia web application. Quiziverse is designed to engage&#8230;]]></description>
										<content:encoded><![CDATA[
<p>March’s topic is Web Apps and I’m excited to introduce my project: Quiziverse, a complete quiz and trivia web application.</p>



<p>Quiziverse is designed to engage users with time-limited questions across various categories, making it a fun and interactive way to test knowledge. The application leverages a SQLite database as the backend for all data storage.</p>



<p>Here are some of the key features of Quiziverse:</p>



<ul class="wp-block-list">
<li><strong>Admin Area:</strong> The app includes a secure admin area, allowing administrators to manage categories and questions easily. Admins can add, edit, or delete questions and categories to keep the trivia fresh and exciting.</li>



<li><strong>Scoreboard:</strong> A dynamic scoreboard keeps track of player scores in real-time, fostering a competitive spirit among users. Players can see how they stack up against others, adding an element of fun to the experience.</li>



<li><strong>Time-Limited Questions:</strong> Each question comes with a timer, challenging players to think quickly and answer before time runs out. This feature adds to the intensity of the game and keeps players on their toes.</li>



<li><strong>Import JSON Files:</strong> To make it easy for admins to add new content, Quiziverse includes a function to import JSON files containing new categories and questions. This feature simplifies content management and allows for quick updates.</li>



<li><strong>Mobile Optimized Design:</strong> Understanding the importance of accessibility, Quiziverse is designed to be mobile-friendly. Players can join the trivia challenge from their smartphones or tablets for a seamless experience.</li>
</ul>



<p>Here’s a sneak peek of the Quiziverse interface:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="487" src="https://blog.xojo.com/wp-content/uploads/2025/03/image-1-1024x487.png" alt="Quiziverse Start Page" class="wp-image-14593" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/image-1-1024x487.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/image-1-300x143.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/image-1-768x365.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/image-1-1536x731.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/image-1.png 1583w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="479" src="https://blog.xojo.com/wp-content/uploads/2025/03/image-1024x479.png" alt="Quiziverse Trivia Page" class="wp-image-14592" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/image-1024x479.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/image-300x140.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/image-768x359.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/image-1536x719.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/image.png 1599w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="485" src="https://blog.xojo.com/wp-content/uploads/2025/03/image-2-1024x485.png" alt="Quiziverse Admin General Settings" class="wp-image-14594" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/image-2-1024x485.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/image-2-300x142.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/image-2-768x364.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/image-2-1536x727.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/image-2.png 1588w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="483" src="https://blog.xojo.com/wp-content/uploads/2025/03/image-3-1024x483.png" alt="Quiziverse Admin Categories" class="wp-image-14595" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/image-3-1024x483.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/image-3-300x141.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/image-3-768x362.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/image-3-1536x724.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/image-3.png 1580w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="483" src="https://blog.xojo.com/wp-content/uploads/2025/03/image-4-1024x483.png" alt="Quiziverse Admin Questions" class="wp-image-14596" srcset="https://blog.xojo.com/wp-content/uploads/2025/03/image-4-1024x483.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/03/image-4-300x141.png 300w, https://blog.xojo.com/wp-content/uploads/2025/03/image-4-768x362.png 768w, https://blog.xojo.com/wp-content/uploads/2025/03/image-4-1536x724.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/03/image-4.png 1584w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You can find the complete source code for <a href="https://github.com/xolabsro/Quiziverse" data-type="link" data-id="https://github.com/xolabsro/Quiziverse" target="_blank" rel="noreferrer noopener">Quiziverse on GitHub</a>, along with detailed documentation to help you get started.</p>



<p>Stay tuned for more exciting projects as we continue our Year of Code 2025 journey!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Year of Code Project</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/">Year of Code: Kickoff</a></li>



<li><a href="https://blog.xojo.com/2025/01/15/year-of-code-2025-january-project/" target="_blank" rel="noreferrer noopener">January Project: Desktop Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/year-of-code-2025-january-project-sharing/83927" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/02/11/year-of-code-2025-february-project/">February Project: Database Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/2025-year-of-code-february" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/03/05/year-of-code-2025-march-project-web-apps/">March Project: Web Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-march/84474?u=alyssa_foley">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/04/08/year-of-code-2025-april-project-user-interface/">April Project: User Interface</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-april-user-interface/84926">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/05/07/year-of-code-2025-may-project-mobile-apps/">May Project: Mobile Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-may-is-mobile/85272">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/06/10/year-of-code-2025-june-project-cross-platform-code-class/">June Project: Code Sharing</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-june-is-code-sharing/85612">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/07/10/year-of-code-2025-july-project-charting/">July Project: Charting</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-july-is-charting/85896">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/08/07/year-of-code-2025-august-project-console-apps/">August Project: Console Apps</a> | <a href="https://forum.xojo.com/t/august-2025-year-of-code-console-apps/86203">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/09/08/year-of-code-2025-september-project-games/">September Project: Games</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-septgamer">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/10/13/year-of-code-2025-october-project-multi-platform-communication/">October Project: Multi-Platform</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-october-multi-platform-communication/86717">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/">November Project: PDF</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-november-pdf/86969">Forum Discussion</a></li>
</ul>



<p><strong>How to Play:</strong></p>



<p>Each month we&#8217;ll announce a new theme and share an example project of our own. Share your projects to the Xojo Forum thread for that month via GitHub (all the links you need are posted above ↑ ). Learn how to use <a href="https://blog.xojo.com/2024/04/02/using-xojo-and-github/">Xojo and GitHub</a>.</p>



<p><strong>The Prizes:</strong></p>



<p>Monthly winners get $100 at the Xojo store. Every month you submit a project is another chance to win the grand prize. The grand prize is $250 cash plus a Xojo Pro license and a year of GraffitiSuite and will be announce in December. Learn more about the <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/#prizes">prizes</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spotlight On: Offroad Portal</title>
		<link>https://blog.xojo.com/2025/02/11/spotlight-on-offroad-portal/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Tue, 11 Feb 2025 20:01:26 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14393</guid>

					<description><![CDATA[Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and spread awareness of community resources. If you have an app, a project or a person you want to see featured in Spotlight On,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</a>!</em></p>



<p>When I started sharing Spotlight On posts last year, Alvaro Fontán was a Xojo developer that immediately came to mind as someone who should have a spotlight shone on their work. Alvaro has been to multiple Xojo Developer Conferences and is a great guy to get into a conversation with, whether about Xojo or a lot of other topics. His <a href="https://offroadportal.org/" target="_blank" rel="noreferrer noopener">Offroad Portal</a> project is a excellent example of an app that solves a problem and helps a community of people. This project continues to grow with  26 current administrators around the country distributing volunteers to all 50 states.</p>



<h3 class="wp-block-heading"><strong>Mac, Windows or Linux?</strong></h3>



<p>I develop in a Mac environment but create applications for Windows, Mac, and Web using Xojo. I primarily use MySQL for all the apps I build and frequently integrate APIs into my projects. I also enjoy incorporating HTML and CSS into Xojo applications to enhance their functionality and user experience.</p>



<h3 class="wp-block-heading"><strong>What do you wish more people would ask/talk to you about regarding programming?</strong></h3>



<p>I wish schools provided more opportunities for young minds to explore programming. Today, everyone carries a powerful computer in their pocket, yet most people have no idea how to create custom tools to truly harness its potential. I think Xojo would be an amazing starting point for them.</p>



<h3 class="wp-block-heading"><strong>How would you explain your most recent project to a 5 year old?</strong></h3>



<p>Many people with little off-road experience end up getting stuck, facing technical difficulties, or breaking down. To address this, we’ve developed a web application that captures the incident location and allows users to share photos, notes, and contact information. Once a request is submitted, administrators verify the situation and forward it to local volunteers across all 50 states. Currently, we have 3 general administrators, over 26 regular administrators, and more than 13,000 dedicated volunteers. Additionally, we have the support of hundreds of thousands of extra volunteers from local off-road organizations we collaborate with. Our application enables real-time tracking of the recovery process, allowing all involved parties to communicate and coordinate effectively.</p>



<h3 class="wp-block-heading"><strong>What&#8217;s next on your &#8220;Learn Next&#8221; list?</strong></h3>



<p>I’m exploring ways to integrate AI to streamline the work of our administrators, as much of their tasks are repetitive and time-consuming.</p>



<h3 class="wp-block-heading"><strong>What is something that has surprised you about coding in the last 10 years?</strong></h3>



<p>Sometimes, after spending hours developing a solution and testing it for days, a user will discover a bug by doing something I never thought to try in my own app.</p>



<h3 class="wp-block-heading"><strong>Xojo isn&#8217;t the only tool in your kit. What is a piece of software more people should know about?</strong></h3>



<p>MySQL, CSS, HTML, Python, AppleScript, JavaScript. </p>



<h3 class="wp-block-heading"><strong>What is&nbsp;something you worked on recently that you want to&nbsp;talk about?</strong></h3>



<p>I received a request from an elderly person who had never used a computer and wanted to learn how to use a simple word processor. After searching for an option that was easy enough to simplify saving, loading, printing, and emailing, I couldn’t find anything suitable. So, in just a few hours, I designed a simple interface using Xojo, integrated it with a MySQL back end, and made it extremely user-friendly—with autosaving, non-destructive editing, and buttons to navigate through different versions. There’s one click to print and one click to send a copy by email.</p>



<p>It may sound simple, but the more I thought about it, the more I realized how overwhelming it must be for someone who’s never used a modern UI to complete even the most basic tasks. Xojo turned out to be the perfect tool for quickly developing solutions like this one.</p>



<h3 class="wp-block-heading"><strong>When did you start using Xojo?</strong></h3>



<p>1998/99.</p>



<h3 class="wp-block-heading"><strong>How did you find Xojo?</strong></h3>



<p>Can&#8217;t remember. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h3 class="wp-block-heading"><strong>What did you first&nbsp;build with Xojo?</strong></h3>



<p>Small apps for helping with things around the office.</p>



<h3 class="wp-block-heading"><strong>When was that?</strong></h3>



<p>The first apps I developed were in the early 2000s. In 2002, with my background in graphic design and while working for a sales magazine, I created the software we used to produce the magazines, utilizing Xojo and AppleScript with Quark. In 2004, I was hired as a full-time developer for the first time, where I automated the creation of brochures and booklets using Xojo and AppleScript.</p>



<p>By 2007, I advanced further and was hired by a large corporation that owned 25 newspapers. There, I developed a photo database that managed and shared about a million photos using Xojo and MySQL. Later, I built an editorial system that automated newspaper design and managed web content for over 200 editors, reporters, and photographers, integrating Xojo with Joomla and later with WordPress for smaller sub-sites.</p>



<p>When the company was sold, I continued maintaining dozens of systems I had developed, working as a contractor for the new owners.</p>



<h3 class="wp-block-heading"><strong>What do you build with it now?&nbsp;</strong></h3>



<p>Our application for Offroad Portal is what consumes most of my time.</p>



<h3 class="wp-block-heading"><strong>Do you earn a living with Xojo?&nbsp;</strong></h3>



<p>Yes, absolutely.&nbsp;</p>



<h3 class="wp-block-heading"><strong>Do you use it for your hobbies?&nbsp;</strong></h3>



<p>It&#8217;s a tool I use, much like someone would use a ruler or a calculator. For me, thinking about implementing solutions with Xojo comes naturally.</p>



<h3 class="wp-block-heading"><strong>What&#8217;s your biggest Xojo success?</strong></h3>



<p>The newspaper software was my proudest achievement. It was a massive undertaking with countless challenges, but also a lot of fun. I worked on that project for over 12 years, and I vividly remember the code reaching over 120,000 lines. I started as the sole developer, but eventually, I was able to build a small team. This allowed me to delegate parts of the code to other developers and get help with web integration.</p>



<p><em>Thank you to Alvaro Fontán for answering questions and sharing his Xojo experience with the community. </em> <em>Learn more about <a href="https://offroadportal.org/how-does-this-work/" target="_blank" rel="noreferrer noopener">Offroad Portal</a>.</em></p>



<p><em>If you have an app, a project or a person you want to see featured in Spotlight On,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</a>!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>More Control Over Your Charts</title>
		<link>https://blog.xojo.com/2024/12/10/more-control-over-your-charts/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:37:02 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r4]]></category>
		<category><![CDATA[Charts]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13985</guid>

					<description><![CDATA[Starting with Xojo 2024r4 the Chart feature provides even more control over how DataSets are drawn through new properties on Desktop, Web and iOS. Also,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2024r4 the Chart feature provides even more control over how DataSets are drawn through new properties on Desktop, Web and iOS. Also, for Desktop, the Chart control adds two new Event handlers to draw the datapoints of the chart in any way you want.</p>



<span id="more-13985"></span>



<h2 class="wp-block-heading">Granular Control on DataSets</h2>



<p>The ChartDataset subclasses add three new properties. Now you can choose to allow the interaction from the user (for example when clicking or taping on data points or over a displayed legend in the Chart), you can also choose what legends are visible at the top area of the Chart, as well as choosing to display a Popover when the user moves the mouse over a given rendered datapoint for the associated ChartDataset.</p>



<ul class="wp-block-list">
<li><strong>AllowInteraction</strong>: When it is set to False, then the displayed legend for the ChartDataset doesn&#8217;t respond to interaction (that is enabling/disabling the associated data in the Chart) or raises the Pressed event for the Chart. Also, it doesn&#8217;t fire the Pressed event when the user clicks on any of the rendered data points in the Chart for that particular DataSet.</li>



<li><strong>IsLegendVisible</strong>: When it is set to False, the Legend for the associated ChartDataset is not displayed at the top area of the Chart (always that the Chart.HasLegend property is set to True). This allows a more granular control over the legends that are displayed, so you can have some of the rendered data sets with their legend displayed while others not.</li>



<li><strong>AllowPopover</strong>: When this property is set to False in the ChartDataset, then the Popover won&#8217;t be displayed when the user hovers the cursor over any of its rendered points in the Chart.</li>
</ul>



<h2 class="wp-block-heading">New Events for Chart on Desktop</h2>



<p>Starting with Xojo 2024r4 you can decide how the Chart should draw the data points for any of the rendered ChartDatasets on Desktop. This is done by implementing the two new Event Handlers on the Chart instance:</p>



<ul class="wp-block-list">
<li><strong>DrawPointAt(g As Graphics, x As Double, y As Double, data As ChartDataSet, index As Integer) As Boolean</strong>. This event receives from the &#8220;g&#8221; parameter the graphic context for the datapoint, so you can use any of the available methods and properties of the Graphics class to draw the datapoint. In order to know what datapoint and from what ChartDataset, these are given in the &#8220;index&#8221; and &#8220;data&#8221; parameters, respectively. Also, the &#8220;x&#8221; and &#8220;y&#8221; parameters receive the coordinates for the top-left corner of the data point to be drawn. These coordinates are relatives to the Chart control instance position. Returning True from this Event means that your code handled the datapoint drawing; otherwise the datapoint will be rendered as usual.</li>



<li><strong>DrawMouseOverPointAt(g As Graphics, x As Double, y As Double, data As ChartDataSet, index As Integer) As Boolean</strong>. This event behaves in the same way as the previous one, the only difference is that it will be raised when the user hovers the cursor over a given datapoint, so you have the chance to decide how to draw the highlighted version of the datapoint.</li>
</ul>



<p>You can learn more about the Chart control in the Xojo Documentation at: <a href="https://documentation.xojo.com/api/user_interface/controls/chart.html#chart">https://documentation.xojo.com/api/user_interface/controls/chart.html#chart</a><br>You can learn more about the ChartDataset class (and subclasses) in the Xojo Documentation at: <a href="https://documentation.xojo.com/api/user_interface/charts/chartdataset.html#chartdataset">https://documentation.xojo.com/api/user_interface/charts/chartdataset.html#chartdataset</a></p>



<p>A big thank you for all of you providing feedback and suggestions about how to improve Charts on Xojo! All of these new additions are a direct response from request made from you, so we are happy to make it work the way you need to adhere even more to your needs!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Xojo Web Improvements in 2024r4</title>
		<link>https://blog.xojo.com/2024/12/10/xojo-web-improvements-in-2024r4/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:36:35 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r4]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo IDE]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14138</guid>

					<description><![CDATA[Making the Web Framework more robust is something we&#8217;ve been working on for years. This release doesn&#8217;t brings too many shiny new toys to play&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Making the Web Framework more robust is something we&#8217;ve been working on for years. This release doesn&#8217;t brings too many shiny new toys to play with, it comes with bug fixes instead that were tricky to fix. Here are some highlights.</p>



<h2 class="wp-block-heading"><strong>Using a WebPopupMenu with a Keyboard</strong></h2>



<p>2024r4 comes with keyboard full support for <a href="https://documentation.xojo.com/api/user_interface/web/webpopupmenu.html#webpopupmenu">WebPopupMenu</a>. We&#8217;ve been gradually improving this control to allow your users to select a field using the arrow keys, for example. What&#8217;s new is being able to go directly to one of the item just by starting to type its name.</p>



<figure class="wp-block-video"><video height="1250" style="aspect-ratio: 1376 / 1250;" width="1376" controls src="https://blog.xojo.com/wp-content/uploads/2024/12/WebPopupMenu-with-keyboard.mp4"></video></figure>



<h2 class="wp-block-heading"><strong>Memory Usage Improvements</strong></h2>



<p>Everyone does their best to avoid leaking memory but, sometimes, that&#8217;s just not enough.</p>



<p><a href="https://blog.xojo.com/2022/12/06/the-versatility-of-xojo/">Jérémie Leroy</a> is known for the success of the mobile apps he makes with Xojo. When one of these successful app requires a Web Service, receiving 1000s of requests, it needs to be as lightweight as possible.</p>



<p>Thanks to his reports, the visual controls will be creating Tooltip and WebCSSClasses instances only when being used. For many projects this won&#8217;t make a difference, but having a Web project with hundreds of concurrent users will surely lead to less memory pressure, allowing to run Web apps in cheaper servers.</p>



<p>This task never ends. Upcoming releases will continue improving memory usage and performance.</p>



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



<p>The library we use to display maps, MapLibre, has been upgraded from 3.2.0 to 4.7.1, which will make much easier to implement some of the features we want to introduce in upcoming releases. Stay tuned!</p>



<p>This control also received 4 additional bug fixes. One of them was causing the Zoom to be modified, when updating another control property, for example.</p>



<h2 class="wp-block-heading"><strong>Some New Features</strong></h2>



<p>While Web received mostly bug fixes this time, it also comes with some hidden gems.</p>



<p>Popover position can be adjusted now when displaying it. The positioning is relative to its parent control. Additionally, you can now use a WebPage as the parent control, instead of one of the page children, to place your Popover exactly where you need.</p>



<p>Last, but not least, my favorite new feature. We&#8217;ve added CallLater method to WebTimer. It works exactly the same as Timer.CallLater, but it&#8217;s Session aware. This means you will be able to access the Session from its callback, without having to do anything special.</p>



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



<p>We are saying goodbye to a 2024 packed with improvements for the Web target, with a release dedicated (more than usual) to bug fixing and to make everything more stable. Make sure to check <a href="https://documentation.xojo.com/resources/release_notes/2024r4.html" data-type="link" data-id="https://documentation.xojo.com/resources/release_notes/2024r4.html">Xojo 2024r4 Release Notes</a>, so you don&#8217;t miss anything.</p>



<p>Thanks to everyone reporting bugs, making feature requests and collaborating in the forum!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/12/WebPopupMenu-with-keyboard.mp4" length="330684" type="video/mp4" />

			</item>
		<item>
		<title>Xojo 2024r4 is Now Available!</title>
		<link>https://blog.xojo.com/2024/12/10/xojo-2024r4-is-now-available/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:36:12 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r4]]></category>
		<category><![CDATA[App Localization]]></category>
		<category><![CDATA[Charts]]></category>
		<category><![CDATA[Code Editor]]></category>
		<category><![CDATA[Hardened Runtime]]></category>
		<category><![CDATA[Notarization]]></category>
		<category><![CDATA[Preemptive Threads]]></category>
		<category><![CDATA[Sandboxing]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14183</guid>

					<description><![CDATA[Xojo 2024 Release 4 introduces a suite of powerful new features and enhancements, along with numerous bug fixes, further solidifying Xojo’s commitment to providing a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2024 Release 4 introduces a suite of powerful new features and enhancements, along with numerous bug fixes, further solidifying Xojo’s commitment to providing a robust and versatile development environment. With 33 new features added and 182 bugs fixed, Xojo 2024r4 is designed to enhance your productivity and expand your creative possibilities.</p>



<h2 class="wp-block-heading">What’s New in Xojo 2024r4</h2>



<p>Xojo 2024r4 brings a range of exciting updates that enhance cross-platform development, improve security, and provide more tools for creating dynamic and interactive applications. Here are some of the standout features:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Android Localization</strong></p>



<p>Expand your app’s reach with comprehensive localization support for Android. Easily add translations and switch locales using the intuitive Constant Editor, allowing you to cater to a diverse, global audience without the hassle.</p>



<p><a href="https://blog.xojo.com/2024/12/10/android-localization/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/android-localization/" target="_blank" rel="noreferrer noopener">Learn more about Android Localization</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Extended Android Features</strong></p>



<p>We&#8217;ve enhanced Android support by integrating several standard Xojo language features, including Structures, ByRef parameters, Operator_Lookup, and Operator_Convert.</p>



<p><a href="https://blog.xojo.com/2024/12/10/android-language-features/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/android-language-features/" target="_blank" rel="noreferrer noopener">Discover the Extended Android Features</a></p>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Selection Matching</strong></p>



<p>Boost your coding efficiency with the new Selection Matching feature in Xojo&#8217;s Code Editor. Quickly highlight and track all occurrences of selected text in your code, making it easier to navigate, refactor, and maintain your projects.</p>



<p><a href="https://blog.xojo.com/2024/12/10/code-editor-selection-matching/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/code-editor-selection-matching/" target="_blank" rel="noreferrer noopener">Learn more about Code Selection Matching</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Secure Mac Apps</strong></p>



<p>Enhance the security of your Mac applications directly from the Xojo IDE with built-in support for Sandboxing, Hardened Runtime, and Notarization. These features ensure your apps meet the latest security standards, providing a safe and trusted experience for your users.</p>



<p><a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" target="_blank" rel="noreferrer noopener">Learn more</a></p>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Enhanced Charts</strong></p>



<p>Take control of your data visualization with Enhanced Charts. Gain precise control over DataSets and legends, and design dynamic, interactive charts using new event handlers and properties. These improvements make it easier to create visually compelling and informative charts for your applications.</p>



<p><a href="https://blog.xojo.com/2024/12/10/more-control-over-your-charts/" target="_blank" rel="noreferrer noopener">Read about the enhanced Charts</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Preemptive Threads</strong></p>



<p>Experience faster execution, better debugging, and smarter object handling with the enhanced Preemptive Threads. This feature maximizes your application’s performance on multi-core systems, allowing for more responsive and efficient code.</p>



<p><a href="https://blog.xojo.com/2024/12/10/sharpening-our-preemptive-threads/" target="_blank" rel="noreferrer noopener">Understand Preemptive Threads</a></p>
</div>
</div>



<p><strong>Web Framework</strong><br>Enjoy smoother and more efficient web applications with updates to Xojo&#8217;s Web Framework. Improved memory usage and numerous bug fixes ensure that your web apps run reliably and perform optimally, providing a better experience for your users.</p>



<p><a href="https://blog.xojo.com/2024/12/10/xojo-web-improvements-in-2024r4/" target="_blank" rel="noreferrer noopener">Discover Web Framework Improvements</a></p>



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



<p>These updates and enhancements are designed to make your development process more efficient, productive, and enjoyable. Whether you’re building new applications or enhancing existing ones, Xojo 2024r4 provides the tools and capabilities you need to succeed.</p>



<h2 class="wp-block-heading">Get Started</h2>



<p>To learn more about Xojo 2024 Release 4 and begin your development journey, please visit the&nbsp;<a href="https://documentation.xojo.com/versions/2024r4/resources/release_notes/2024r4.html" target="_blank" rel="noreferrer noopener">Xojo 2024r4 Release Notes</a>. The update is available for download now from the&nbsp;<a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Xojo downloads page</a>.</p>



<h3 class="wp-block-heading">What’s Next?</h3>



<p>We’re continuously working on new features, updates, and enhancements to our platform. If you have any suggestions or ideas, please add them to the&nbsp;<a href="https://tracker.xojo.com/xojoinc/xojo">Xojo tracker</a>. We’re always looking to improve and expand Xojo to better serve our community.</p>



<p><strong>Thank you for being part of the Xojo community. We’re excited to see what you create with Xojo 2024r4!</strong></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Working with PDFTableDataSource from Sources Other Than RowSet</title>
		<link>https://blog.xojo.com/2024/11/25/working-with-pdftabledatasource-from-sources-other-than-rowset/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 25 Nov 2024 14:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[PDF]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14035</guid>

					<description><![CDATA[Some users on the Xojo Forum recently asked how to render tables on a PDFDocument using the PDFTableDataSource class interface when the dat source does&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Some users on the <a href="https://forum.xojo.com/t/pdftable-created-manually-not-from-rowset-web/83000">Xojo Forum recently</a> asked how to render tables on a PDFDocument using the <a href="https://documentation.xojo.com/api/pdf/pdftabledatasource.html#pdftabledatasource">PDFTableDataSource</a> class interface when the dat source does not comes from a RowSet. Well, the truth is that it doesn&#8217;t differ too much from when it does! Continue reading and I will show you how using a simple example.</p>



<span id="more-14035"></span>



<p>The trick is to handle the data coming from any source with the right data structure, for example, an Array. This example uses a plain text file with several lines and columns separated by the Tab character as the source of the data.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>In order to follow this tutorial, <a href="https://drive.google.com/file/d/14Ve5TllFLGK2TE4MTr4fjutpI4aGV0UE/view?usp=sharing">download the example project</a>.</p>
</blockquote>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1816" height="2378" src="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22.png" alt="" class="wp-image-14041" srcset="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22.png 1816w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-229x300.png 229w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-782x1024.png 782w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-768x1006.png 768w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-1173x1536.png 1173w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-1564x2048.png 1564w" sizes="auto, (max-width: 1816px) 100vw, 1816px" /></figure>
</div>


<h2 class="wp-block-heading">Getting the Data</h2>



<p>As you can see in the example project, the text file has been added to the project using a Build > Copy Files Step (the file name is &#8220;Data.txt&#8221;), so it is copied to the Resources folder of the compiled app and available for both debugging and release builds.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2224" height="1464" src="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01.png" alt="" class="wp-image-14037" srcset="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01.png 2224w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-300x197.png 300w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-1024x674.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-768x506.png 768w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-1536x1011.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-2048x1348.png 2048w" sizes="auto, (max-width: 2224px) 100vw, 2224px" /></figure>
</div>


<p>Then, in the Pressed event of the Button1 control placed on the default Window1, we will access the contents of the file in order to store each of the lines in the Data Array of strings:</p>



<pre class="wp-block-code"><code>Var f As FolderItem = SpecialFolder.Resource("data.txt")
If f &lt;&gt; Nil And f.Exists Then
  Var tis As TextInputStream = TextInputStream.Open(f)
  Var s As String = tis.ReadAll
  data = s.ToArray(EndOfLine.macOS)
End If</code></pre>



<h2 class="wp-block-heading">PDFRenderer Subclass</h2>



<p>The next step is to create a custom class that will implement the methods provided by the PDFTableDataSource Class Interface. We will name the class &#8220;PDFRenderer&#8221;. Then, from the Inspector Panel, click on the Interfaces button, check the PDFTableDataSource interface and confirm the selection.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1076" height="1004" src="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21.png" alt="" class="wp-image-14036" srcset="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21.png 1076w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21-300x280.png 300w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21-1024x955.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21-768x717.png 768w" sizes="auto, (max-width: 1076px) 100vw, 1076px" /></figure>
</div>


<p>Once done, the methods from the class interface will be automatically added to the class:</p>



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



<li>Completed</li>



<li>HeaderHeight</li>



<li>MergeCellsForRow</li>



<li>PaintCell</li>



<li>PaintHeaderContent</li>



<li>RowHeight</li>
</ul>



<p>Over these we will add three more methods:</p>



<h4 class="wp-block-heading">The class Constructor:</h4>



<pre class="wp-block-code"><code>Public Sub Constructor(document As PDFDocument)
  // Simple constructor… just assign the received object
  // to the "Document" property
  
  Self.document = document
  proxy = New Picture(document.Graphics.Width, document.Graphics.Height)
End Sub</code></pre>



<p>Assign the received PDFDocument instance to the document property. It also creates a graphics instance that will be used as a proxy for calculating the height of the processed text from the data (that won&#8217;t be necessary starting with Xojo 2024r4 where some PDFDocument bugs related with that are already fixed).</p>



<h4 class="wp-block-heading">DrawTable:</h4>



<p>This method is the one that will be called to start drawing the table. It will initialize some properties from the received Data (yeah, you can see a property named as &#8220;DrawingFromRowSet&#8221;, but I left that one on purpose because this project is based on the one dealing with the data coming from a RowSet, so you can see how similar all the process is):</p>



<pre class="wp-block-code"><code>Public Sub DrawTable(data() As String, headers() As String)
  // This is the method we call on the Class to draw
  // a table on a PDFDocument based on an Array of Strings
  
  If document &lt;> Nil And data.LastIndex &lt;> -1 Then
    
    // Assign the received Array to the "Data" property
    Self.data = data
    
    // Assign the received headers to the "Headers" property
    Self.Headers = Headers
    
    // Hey! We are going to create a table from an Array
    // so we use a Boolean property as a flag for that
    // (Yeah, we can do it using other techniques, but this
    // is easy enough for this purpose… while leave this
    // helper class "open" enough for drawing tables based on other
    // data sources).
    Self.DrawingFromRowSet = True
    
    // How many columns are we going to draw?
    // Well… as many as columns (TABs) in any of the Array items (for example, the first one).
    Var totalColumns As Integer = data(0).CountFields(Chr(9))
    
    // This is going to be the "drawable area" on the page
    // for the table = total page width less the left and right margins
    Var totalWidth As Double = document.Graphics.Width - 40 // 40 = 20 points left/right margins
    
    // Creating the PDFTable object here!
    Var table As New PDFTable
    
    // We want to repeat the headers on every page
    table.HasRepeatingHeader = True
    
    // Setting the column count for the table
    table.ColumnCount = totalColumns
    
    // …and the width for every column.
    table.ColumnWidths = CalculateColumnWidths(totalWidth, totalColumns)
    
    // The object from this class will be the responsible
    // of handling all the methods associated with the
    // PDFTableDataSouce Class Interface
    table.DataSource = Self
    
    // Setting the Top and Bottom margins for the drawing
    // of the table on every PDF page
    table.TopMargin = 20
    table.BottomMargin = 20
    
    // …and finally we instruct the PDFDocument object
    // to draw the table!
    document.AddTable(table, 20, 0)
    
    // Lastly, clearing the flag
    Self.DrawingFromRowSet = False
    
  End If
End Sub</code></pre>



<h4 class="wp-block-heading">CalculateColumnWidths Method</h4>



<p>This one will calculate the widths for each column to be rendered in the final PDF document.</p>



<pre class="wp-block-code"><code>Protected Function CalculateColumnWidths(TotalWidth As Double, NumberOfColumns As Double) As String
  // Helper method to get a string for the column widths
  
  ColumnWidth = TotalWidth / NumberOfColumns
  Var s() As String
  
  For n As Integer = 0 To NumberOfColumns - 1
    s.Add(Str(ColumnWidth))
  Next
  
  Return String.FromArray(s, ",")
End Function</code></pre>



<h3 class="wp-block-heading">Class Properties</h3>



<p>Because we need to track things like what the current row or column is to be rendered, the headers, etc., our class needs to add some properties:</p>



<ul class="wp-block-list">
<li>Protected Property ColumnWidth As Integer</li>



<li>Public Property CurrentColumn As Integer</li>



<li>Protected Property CurrentHeight As Integer</li>



<li>Protected Property CurrentRow As Integer</li>



<li>Protected Property data() As String</li>



<li>Protected Property document As PDFDocument</li>



<li>Protected Property DrawingFromRowSet As Boolean</li>



<li>Public Property Headers() As String</li>



<li>Protected Property LastRow As Integer</li>



<li>Protected Property proxy As Picture</li>
</ul>



<h3 class="wp-block-heading">PDFTableDataSouce Methods</h3>



<p>Time to visit the methods added by the PDFTableDataSouce class interface. These are the methods called by the <a href="https://documentation.xojo.com/api/pdf/pdftable.html#pdftable">PDFTable</a> object each time it needs to retrieve a piece of information during the rendering on the PDFDocument, as for example if it needs to add a new row, the height for the Header or the current row… and the painting of the row itself!</p>



<h4 class="wp-block-heading">AddNewRow Method</h4>



<p>This one is called by the PDFTable object in order to know if it needs to render a new row in the table:</p>



<pre class="wp-block-code"><code>Protected Function AddNewRow(rowCount As Integer) As Boolean
  // Part of the PDFTableDataSource interface.
  
  If DrawingFromRowSet And data.LastIndex &lt;> -1 then
    
    // We are going to draw as many rows as rows are in the
    // "data" array
    Return rowCount &lt;= data.LastIndex
    
  End If
End Function</code></pre>



<h4 class="wp-block-heading">Completed method</h4>



<p>This is the method invoked by the PDFTable object when it finished drawing the table, so it is your chance to take additional operations, for example, numbering every page of the PDFDocument (we can&#8217;t anticipate that before drawing the table itself):</p>



<pre class="wp-block-code"><code>Protected Sub Completed(x As Double, y As Double)
  // Part of the PDFTableDataSource interface.
  
  // This method is called once the table has been drawed
  // so let's "print" the page number on every page
  // of the PDF Document
  
  Static pageNumber As String = "Page: "
  
  If document &lt;> Nil Then
    Var g As Graphics = document.Graphics
    
    For n As Integer = 1 To document.PageCount
      document.CurrentPage = n
      g.DrawText(pageNumber + Str(n), g.Width - g.TextWidth(pageNumber + Str(n)) - 20, g.Height - g.FontAscent)
    Next
    
  End If
End Sub</code></pre>



<h4 class="wp-block-heading">HeaderHeight Method</h4>



<p>This is the method called by the PDFTable object the returns the height we want to use for rendering the header on the first page and, optionally, on every new page required (added to the document) by rendering the table. In this case we will return a fixed value:</p>



<pre class="wp-block-code"><code>Protected Function HeaderHeight() As Double
  // Part of the PDFTableDataSource interface.
  
  // Returning a fixed height value for the headers
  Return 20
End Function</code></pre>



<h4 class="wp-block-heading">MergeCellsForRow Method</h4>



<p>The PDFTableDataSouce class interface also has the ability to merge cells in the current row, so you can create more elaborated tables. We are not going to use that feature in this example project so it will be empty, no code to be executed.</p>



<h4 class="wp-block-heading">PaintHeaderContent Method</h4>



<p>This is the method in charge of rendering the header for the table, so it receives its own Graphic context with the provided height from the HeaderHeight method and the width calculated from the total of columns (headers) needed to be rendered:</p>



<pre class="wp-block-code"><code>Protected Sub PaintHeaderContent(g As Graphics, column As Integer)
  // Part of the PDFTableDataSource interface.
  
  // Painting the headers for the table
  If column &lt;= Self.Headers.LastIndex Then
    
    Var s As String = headers(column)
    g.DrawingColor = Color.Black
    g.FillRectangle(0, 0, g.Width, g.Height)
    g.DrawingColor = Color.White
    g.DrawText(s, g.Width / 2 - g.TextWidth(headers(column)) / 2, g.Height / 2 + g.FontAscent / 2)
    
  End If
End Sub</code></pre>



<h4 class="wp-block-heading">RowHeight Method</h4>



<p>As the class interface provides a method so we can provide the height for the header, we also have a RowHeight method that the PDFTable object will call before it calls the method in charge of doing the row drawing itself. That way we can have rows of different height based on the height of the own text to be rendered!</p>



<pre class="wp-block-code"><code>Protected Function RowHeight() As Double
  // Part of the PDFTableDataSource interface.
  
  // We need to calculate the height for every row in the Table
  // so let's calculate that based on the taller of the texts (columns)
  // based on text wrapping
  
  If CurrentRow &lt;= data.LastIndex Then
    CurrentHeight = 0
    Var s() As String = data(CurrentRow).Split(Chr(9))
    Var g As Graphics = proxy.Graphics
    Var itemHeight As Integer
    For Each item As String In s
      itemHeight = g.TextHeight(item, ColumnWidth - 40)
      If itemHeight > CurrentHeight Then
        CurrentHeight = itemHeight
      End If
    Next
    
    CurrentRow = CurrentRow  + 1 
    
    Return CurrentHeight + 20
  End If
End Function</code></pre>



<h4 class="wp-block-heading">PaintCell Method</h4>



<p>Lastly, this is the method called by the PDFTable object when it is time to render a given cell for the current row in the table. It receives as parameters both a <a href="https://documentation.xojo.com/api/pdf/pdfgraphics.html#notes">graphic context</a> with the width and height already suited for the data to be rendered, and also the row and column values so you can get the appropriate data for a given cell from the data source:</p>



<pre class="wp-block-code"><code>Protected Sub PaintCell(g As Graphics, row As Integer, column As Integer)
  // Part of the PDFTableDataSource interface.
  
  // Here is where we really do the drawing
  // the received "g" parameter is for a particula table cell
  // based on the row / column parameters
  // so the origin for X/Y coordinates is at 0,0
  
  If DrawingFromRowSet And data.LastIndex >= row Then
    // Drawing the outer rectangle for the cell
    g.DrawRectangle(0, 0, g.Width, g.Height)
    
    // retrieving the text to be drawn from the Array,
    // using the row and column parameters for that.
    Var s As String = data(row).NthField(Chr(9), column + 1)
    
    // Centering vertically the text on the table cell
    // while the X offset is fixed at 5 points.
    g.DrawText(s, 5, g.Height / 2 + g.FontAscent / 2, ColumnWidth - 20)
    
    // Let's keep track of the last row drawed
    LastRow = row
    
  End If
End Sub</code></pre>



<h2 class="wp-block-heading">Time to push the Start button!</h2>



<p>Everything is setup now in our PDFRenderer class, so let&#8217;s get back to the Pressed event of the Button1 control on the default Window1 window. You will remember from the beginning of this tutorial that this is the place where we retrieved the data from the text file. So let&#8217;s add the code to create a PDFDocument instance, a new PDFRenderer instance and do the rendering of the table itself from the data:</p>



<pre class="wp-block-code"><code>If data.LastIndex &lt;&gt; -1 Then
  
  // Creating a new PDFDocument Instance
  Var d As New PDFDocument
  
  // Creating the PDFTable renderer helper object (we pass the PDFDocument object to it in the Constructor)
  Var PDFRender As New PDFRenderer(d)
  
  // These will be the headers drawed in the Table
  Var headers() As String = Array("Name", "Surname", "Address", "City", "Email")
  
  // And let's instruct the PDFTable renderer helper to draw the table
  // based in the SQLite database rowset we got in the previous step
  PDFRender.DrawTable(data, headers)
  
  // …and save the resulting PDF File to the Desktop
  Var out As FolderItem = SpecialFolder.Desktop.Child("TableFromTextFile.pdf")
  
  If out &lt;&gt; Nil Then
    d.Save(out)
    out.Open
  End If
End If</code></pre>



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



<p>As you see, and if this tutorial is compared with <a href="https://blog.xojo.com/2023/01/17/pdftable-from-a-rowset/">PDFTable from a RowSet</a>, creating a PDFTable doesn&#8217;t differ too much when using a data source other than a RowSet. All you need, basically, is to keep track of the current row, know if you need to render more rows and a base data structure that can be used to retrieve the data to be rendered in a given Row/Column.</p>



<p>As always, you can learn more about other features provided by <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html#pdfdocument">PDFDocument in the Xojo Documentation</a>.</p>



<p>Happy Coding!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Xojo Web Rescues a .NET Project</title>
		<link>https://blog.xojo.com/2024/10/23/xojo-web-rescues-a-net-project/</link>
		
		<dc:creator><![CDATA[Wayne Golding]]></dc:creator>
		<pubDate>Wed, 23 Oct 2024 16:40:14 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Encryption]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[URLConnection]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13909</guid>

					<description><![CDATA[I had a call recently from a customer whose upstream supplier informed them that they would not be accepting anything less than TLS 1.2 encryption.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>I had a call recently from a customer whose upstream supplier informed them that they would not be accepting anything less than TLS 1.2 encryption. The customer’s application is written using .NET 1.1 (they are testing a new version but aren’t ready to deploy to production just yet). Their supplier insisted on a 1-week time limit. Can I help?</p>



<p>My answer was, of course, “Let me have a look and get back to you.”</p>



<p>I went to my favourite dev tool, Xojo, and went through the process of developing a solution.&nbsp;The connection is a REST API, so I’ll start with a web project and use the HandleURL event. And I’ll use a URLConnection to pass on the request.&nbsp; Wait … could it be that simple?</p>



<pre class="wp-block-code"><code>Function HandleURL(request As WebRequest, response As WebResponse) Handles HandleURL as Boolean

  // Create the outbound connection
  Var connector As New URLConnection
 
  // Copy the content of the request
  connector.SetRequestContent(request.Body, request.MIMEType)

  // Send the request
  Var result As String
  Try
    result = connector.SendSync("POST", kAddress + request.Path)
  Catch err As RuntimeException
    // Catch DNS, Certificate &amp; Timeout errors
    response.Status = 500
    response.Write(err.Message)
    Return True
  End

  // Return the result of the request
  response.Status = connector.HTTPStatusCode
  response.Write(result)

  Return True

End Function</code></pre>



<p>The answer is, &#8220;Yes!&#8221;&nbsp; This is all the code in the entire project.</p>



<p>You will notice that there is no security, but in this instance that is fine as the virtual machine is running this is on the same network as the client server and the firewall is configured to only allow connections from that server.</p>



<p>After processing over 60 thousand requests, memory use is 7.3MB and never exceeded 13MB.&nbsp;CPU usage was at the maximum 1.5%.</p>



<p>Even after using Xojo for 20 years this still blows my mind.</p>



<p><em>Wayne Golding has been a Xojo developer since 2005 and is a Xojo MVP. He operates the IT Company <a href="http://www.axisdirect.nz">Axis Direct Ltd </a>which primarily develops applications using Xojo that integrate with Xero www.xero.com. Wayne’s hobby is robotics where he uses Xojo to build applications for his Raspberry Pi, often implementing IoT for remote control.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Create Fast RESTful APIs in Xojo</title>
		<link>https://blog.xojo.com/2024/10/14/create-fast-restful-apis-in-xojo/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Mon, 14 Oct 2024 12:01:31 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[API Development]]></category>
		<category><![CDATA[Backend Development]]></category>
		<category><![CDATA[Client-Server Architecture]]></category>
		<category><![CDATA[Data Communication]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Microservices]]></category>
		<category><![CDATA[Server-Side Programming]]></category>
		<category><![CDATA[Web API]]></category>
		<category><![CDATA[Web Service]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13881</guid>

					<description><![CDATA[Application programming interfaces (APIs) are essential for enabling digital interactions. They facilitate communication and data sharing between systems, forming the backbone of many applications and&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Application programming interfaces (APIs) are essential for enabling digital interactions. They facilitate communication and data sharing between systems, forming the backbone of many applications and services.</p>



<p>This article examines Xojo&#8217;s capabilities by building a simple web API service. You will learn to handle different HTTP methods, manage requests, and send meaningful responses. Xojo&#8217;s simplicity makes it an excellent choice for experienced developers transitioning from other languages, as well as those familiar with its user-friendly language.</p>



<h3 class="wp-block-heading">Foundation: The HandleURL Function</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-ad2f72ca wp-block-group-is-layout-flex">
<p>At the heart of every Xojo-developed web API service is the <a href="https://documentation.xojo.com/api/web/webapplication.html#webapplication-handleurl" target="_blank" rel="noreferrer noopener">HandleURL</a> function, included in the App class, responsible for handling the request-response cycle. It receives incoming web requests (<a href="https://documentation.xojo.com/api/web/webrequest.html" target="_blank" rel="noreferrer noopener">WebRequest</a>), processes them based on their characteristics, and crafts appropriate responses (<a href="https://documentation.xojo.com/api/web/webresponse.html" target="_blank" rel="noreferrer noopener">WebResponse</a>) to send back.</p>
</div>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="286" height="79" src="https://blog.xojo.com/wp-content/uploads/2024/10/image.png" alt="" class="wp-image-13882"/></figure>
</div>


<h3 class="wp-block-heading">Defining API Endpoints for GET Requests</h3>



<p>GET requests are primarily used to retrieve data. To handle these requests effectively, let&#8217;s see how to define API endpoints that correspond to specific data or actions in the following code example:</p>



<pre class="wp-block-code"><code>If request.Method = "GET" Then
  Select Case request.Path
  <strong>Case "time"</strong>
    Var currentTime As String = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
    response.Write("{""message"": """ + currentTime + """}")
    response.Status = 200
    Return True
  <strong>Case "hello"</strong>
    response.Write("{""message"": ""Hello, World!""}")
    response.Status = 200
    Return True
  End Select
End If</code></pre>



<p>Here, we define two endpoints: /time and /hello.</p>



<p>A GET request to /time will return the current date and time in JSON format, while a request to /hello will return a friendly &#8220;Hello, World!&#8221; greeting.</p>



<p>The response.Status is set to 200, indicating a successful response. Learn more here about <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" data-type="link" data-id="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank" rel="noreferrer noopener">HTTP status codes</a>.</p>



<h3 class="wp-block-heading">Defining API Endpoints for POST Requests</h3>



<p>While GET requests primarily retrieve data, POST requests submit data to the API for processing. Consider submitting a form online – you are sending data to the server via a POST request.</p>



<pre class="wp-block-code"><code>If request.Method = "POST" Then
  Select Case request.Path
  <strong>Case "some-data"</strong>
    Try
      Var jReceivedData As New JSONItem(request.Body)
      Response.Write(jReceivedData.ToString)
      Response.Status = 200
      Return True
    Catch e As JSONException
      response.Write("{""error"": ""Internal Server Error""}")
      response.Status = 500
      Return True
    End Try
  End Select
End If</code></pre>



<p>In this example, a POST request to the /some-data endpoint expects to receive JSON data (<a href="https://documentation.xojo.com/api/web/webrequest.html#webrequest-body" target="_blank" rel="noreferrer noopener">request.Body</a>) for processing.</p>



<p>If the data is successfully parsed, the API responds with the received data.</p>



<p>Otherwise, an error status and message are returned to the client.</p>



<h3 class="wp-block-heading">Bringing it all Together</h3>



<p>Now that you know how to manage &#8220;GET&#8221; and &#8220;POST&#8221; requests, you can start building more complex APIs, with different endpoints available for different methods. To further illustrate API endpoint development, consider the following detailed code example that can be used as template:</p>



<pre class="wp-block-code"><code>Function HandleURL(request As WebRequest, response As WebResponse) Handles HandleURL as Boolean
  response.MIMEType = "application/json"
  
  Try
    Select Case request.Method
    Case "GET"
      
      Select Case request.Path
      Case "time"
        Var currentTime As String = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        response.Write("{""message"": """ + currentTime + """}")
        response.Status = 200
        Return True
      Case "hello"
        response.Write("{""message"": ""Hello, World!""}")
        response.Status = 200
        Return True
      Else
        response.Write("{""error"": ""Not Found""}")
        response.Status = 404
        Return True
      End Select
      
    Case "POST"
      
      Select Case request.Path
      Case "some-data"
        Try
          Var jReceivedData As New JSONItem(request.Body)
          Response.Write(jReceivedData.ToString)
          Response.Status = 200
          Return True
        Catch e As JSONException
          response.Write("{""error"": ""Internal Server Error""}")
          response.Status = 500
          Return True
        End Try
      Else
        response.Write("{""error"": ""Not Found""}")
        response.Status = 404
        Return True
      End Select
      
    End Select
    
  Catch e As RuntimeException
    response.Write("{""error"": ""Internal Server Error""}")
    response.Status = 500
    Return True
  End Try
  
  response.Write("{""error"": ""Not Found""}")
  response.Status = 404
  Return True
  
End Function</code></pre>



<p>Small note: observe the start line within the HandleURL function.</p>



<pre class="wp-block-code"><code>response.MIMEType = "application/json"</code></pre>



<p>This line of code informs the client (browser, application) that the API service is responding using the JSON format. Setting the MIMEType to &#8220;application/json&#8221; is best practice and helps prevent any potential parsing errors on the client side.</p>



<h3 class="wp-block-heading">Next Steps</h3>



<p>You might notice that some code is repeating itself (hint: the error responses), so a good idea would be to create a helper method that deals with this particular type of code repetition. Additionally, consider moving the code from the HandleURL function to a separate method that is then invoked within the HandleURL function for improved organization. This restructuring will enhance code organization, making it easier to maintain, read, and improve the efficiency of the program.</p>



<p>P.S.: You should also check the <a href="https://blog.xojo.com/2024/09/24/microservices-building-modern-scalable-applications/" data-type="link" data-id="https://blog.xojo.com/2024/09/24/microservices-building-modern-scalable-applications/" target="_blank" rel="noreferrer noopener">article about microservices</a> and their purpose to get a better idea of what kind of API interfaces you can create.</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Introducing Named Color and CSS Classes in Xojo Web</title>
		<link>https://blog.xojo.com/2024/10/01/introducing-named-color-and-css-classes-in-xojo-web/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 15:32:13 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r3]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo IDE]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13668</guid>

					<description><![CDATA[The latest Xojo release is a big leap forward in terms of design options for Xojo Web users. Xojo 2024r3 comes with new tools for&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The latest Xojo release is a big leap forward in terms of design options for Xojo Web users. Xojo 2024r3 comes with new tools for making beautiful web applications with less effort.</p>



<h2 class="wp-block-heading">A Quick Reminder About What Bootstrap Is</h2>



<p>As I will be mentioning it during this post, let me take a moment to remind readers what Bootstrap is, and what are we using it for at Xojo.</p>



<p>Bootstrap is the library we use for the visual part of web applications made with Xojo. You can think about it as Gtk on Linux, or UIKit on iOS.</p>



<p>While there is a vast amount of alternative libraries, it&#8217;s been probably the most popular framework for the last decade. You can check the <a href="https://getbootstrap.com" data-type="link" data-id="https://getbootstrap.com" target="_blank" rel="noreferrer noopener nofollow">Bootstrap website</a> for more information.</p>



<h2 class="wp-block-heading">ColorGroup Named Colors</h2>



<p>Until this release, the Named option when configuring a ColorGroup was not available on web projects. 2024r3 brings the ability to choose from the Web Basic colors, Web Extended colors and, what I find more interesting, Bootstrap colors, which also support dark mode out of the box.</p>



<figure class="wp-block-video"><video height="908" style="aspect-ratio: 1448 / 908;" width="1448" controls src="https://blog.xojo.com/wp-content/uploads/2024/09/named-colors-from-the-ide.mp4"></video></figure>



<p>As you can expect, if you drop a custom Bootstrap 5.3 theme with another set of colors, the IDE will automatically update in order to preview them.</p>



<figure class="wp-block-video"><video height="908" style="aspect-ratio: 1436 / 908;" width="1436" controls src="https://blog.xojo.com/wp-content/uploads/2024/09/named-colors-bootstrap-theme-support.mp4"></video></figure>



<h2 class="wp-block-heading">Using Named Colors by Code</h2>



<p>When a dynamic need arises, it is also possible to use Bootstrap Named colors programmatically, if you find it easier. Here is an example:</p>



<pre class="wp-block-code"><code>Var colorName As String

If paymentCardIsValid Then
  colorName = "success"
Else
  colorName = "danger"
End If

Rectangle1.BackgroundColor = ColorGroup.NamedColor(colorName)</code></pre>



<p>Or in a <code>WebCanvas.Paint</code> event:</p>



<pre class="wp-block-code"><code>Var colorName As String = If(paymentCardIsValid, "success", "danger")
g.DrawingColor = ColorGroup.NamedColor(colorName)
g.FillRectangle(0, 0, g.Width, g.Height)</code></pre>



<p>You can check the list of available colors in the <a href="https://getbootstrap.com/docs/5.3/customize/color/" data-type="link" data-id="https://getbootstrap.com/docs/5.3/customize/color/" target="_blank" rel="noreferrer noopener nofollow">Color section of the official Bootstrap documentation</a>. Basic and Extended Web Colors will work as well.</p>



<h2 class="wp-block-heading">Using Bootstrap CSS Classes</h2>



<p>Bootstrap comes with a set of utility CSS classes for a variety of visual things. You probably won&#8217;t need them all, as the Xojo IDE will get you there in most of the cases, and we work hard improving the IDE to make it easier, release by release.</p>



<p>That said, if you are an advanced user, and you have previous experience working with Bootstrap, you may find it useful to add CSS classes directly from the Inspector.</p>



<p>Go to the Advanced tab, add some Bootstrap CSS classes, separated by spaces&#8230; and voilà!</p>



<p>Here is a demo:</p>



<figure class="wp-block-video"><video height="910" style="aspect-ratio: 1652 / 910;" width="1652" controls src="https://blog.xojo.com/wp-content/uploads/2024/09/css-classes-demo.mp4"></video></figure>



<p>We have included a new example, called &#8220;Applying Bootstrap CSS classes to controls&#8221;, that you can find under Platforms &gt; Web. Please give it a try.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="807" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-10.56.29-1024x807.png" alt="" class="wp-image-13672" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-10.56.29-1024x807.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-10.56.29-300x236.png 300w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-10.56.29-768x605.png 768w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-10.56.29.png 1267w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>CSS Classes are not limited to Bootstrap, if you have added styles in the HTML Header section, you can use them as well.</p>



<p>You can also add and remove them using the new <code>CSSClasses</code> property, which is available in every WebUIControl subclass.</p>



<h2 class="wp-block-heading">WebRectangle Got Some Love</h2>



<p>You won&#8217;t need to setup the border color, border thickness or the corner size, for WebRectangle, in the Opening event anymore.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="702" height="853" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-11.02.31.png" alt="" class="wp-image-13673" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-11.02.31.png 702w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-18-a-las-11.02.31-247x300.png 247w" sizes="auto, (max-width: 702px) 100vw, 702px" /><figcaption class="wp-element-caption">Xojo 2024r2.1 on the left, Xojo 2024r3 on the right</figcaption></figure>
</div>


<p>When designing web applications, I found myself using a lot of WebRectangle controls and, by default, they have a rounded border.</p>



<p>The side-effect is subtle, but now that you can control the border radius directly from the Inspector, the IDE preview will be closer to how it will look in the browser. And you are going to avoid writing a few lines of code!</p>



<p>In addition, some Bootstrap themes define a different Corner Size. Setting this property to &#8220;-1&#8221; will honor that Bootstrap theme&#8217;s default border radius.</p>



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



<p>As always, the release comes with much more than I can tell you about in one blog post. With over 30 Bug fixes and 9 Feature Requests implemented in the Web target alone, make sure to take a look at the <a href="https://documentation.xojo.com/resources/release_notes/2024r3.html" data-type="link" data-id="https://documentation.xojo.com/resources/release_notes/2024r3.html" target="_blank" rel="noreferrer noopener">Xojo 2024r3 Release Notes</a> to see the whole picture.</p>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/09/named-colors-from-the-ide.mp4" length="837283" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/09/named-colors-bootstrap-theme-support.mp4" length="429757" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/09/css-classes-demo.mp4" length="721074" type="video/mp4" />

			</item>
		<item>
		<title>Cosmic Trader: A Game Built with Xojo Web</title>
		<link>https://blog.xojo.com/2024/09/17/cosmic-trader-a-game-built-with-xojo-web/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 17 Sep 2024 20:09:12 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Container]]></category>
		<category><![CDATA[Games]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[WebListBox]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13618</guid>

					<description><![CDATA[I truly enjoy creating things with Xojo. This time, I built a little game with Xojo Web just to see if it was possible. In&#8230;]]></description>
										<content:encoded><![CDATA[
<p>I truly enjoy creating things with Xojo. This time, I built a little game with Xojo Web just to see if it was possible. In this post, I will talk about what I liked and what I had difficulties with while programming it.</p>



<p>The reason to create this kind of project, as the maintainer of the Xojo Web framework, is to find pain points and bugs in larger projects, as the issue reports I normally work with are very specific sample projects demonstrating a bug. The next Xojo release, 2024r3, will come with some bug fixes I found while building Cosmic Trader.</p>



<h2 class="wp-block-heading">Final Result</h2>



<p>Let&#8217;s begin at the end. Give the game a try and then come back to this blog post. It&#8217;s a very simple space trading game, don&#8217;t expect too much from it, but I hope you enjoy it.</p>



<p>It can be played from the following URL:<br><a href="https://cosmictrader.rcruz.es" target="_blank" rel="noreferrer noopener nofollow">https://cosmictrader.rcruz.es</a></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="625" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.16-1024x625.png" alt="" class="wp-image-13619" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.16-1024x625.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.16-300x183.png 300w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.16-768x469.png 768w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.16.png 1252w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="625" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.32-1024x625.png" alt="" class="wp-image-13620" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.32-1024x625.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.32-300x183.png 300w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.32-768x469.png 768w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-8.53.32.png 1252w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



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



<p>Create a simple game using Xojo Web, without writing a line of JavaScript, or even using the Web SDK.</p>



<p>In addition, while all this could be just a couple of WebListBox and WebButton controls, I really wanted this game to look like an actual game. As you can see in the screenshots, unless you check the code, nobody will notice (or care!) it&#8217;s a Xojo Web application.</p>



<p>As you can imagine, Xojo Web was not created with the idea of building web based games. In order to make it easier for the developer, everything is processed server side: When you press a button, the browser will send a notification to the server, your code written in Xojo will be executed and, finally, the response will be sent back to the browser.</p>



<p>That&#8217;s the known knowns. I knew the latency would be a problem, but I&#8217;ve found more.</p>



<h2 class="wp-block-heading">What I&#8217;ve Enjoyed</h2>



<p>Implementing the first prototype was really easy using the tools Xojo Web offers. For example, in the prototype, instead of the custom popover I ended up building for buying and selling, I just used some contextual menus:</p>



<figure class="wp-block-video"><video height="732" style="aspect-ratio: 1072 / 732;" width="1072" controls src="https://blog.xojo.com/wp-content/uploads/2024/09/cosmic-trader-early-prototype.mp4"></video></figure>



<p>You can go very far and prototype your idea very quickly this way. This helped me to deploy and share the game with a few friends and gather some initial feedback.</p>



<p>Once you have the game mechanics, you can iterate as much as you want until the game is ready. The welcome screen with the game logo wasn&#8217;t added until very late. Just so you can compare, this is how the current version looks:</p>



<figure class="wp-block-video"><video height="598" style="aspect-ratio: 946 / 598;" width="946" controls src="https://blog.xojo.com/wp-content/uploads/2024/09/cosmic-trader-current-version.mp4"></video></figure>



<p>Much better! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60e.png" alt="😎" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>I&#8217;ve really enjoyed being able to use Containers for building custom controls and reusing them. Also, being able to just drop some images into the IDE and assign them to image viewers is very pleasant.</p>



<p>From the IDE preview, it&#8217;s deadly easy to identify where my ship entity is, click on it, then edit the code if needed:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="720" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-9.32.10-1024x720.png" alt="" class="wp-image-13624" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-9.32.10-1024x720.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-9.32.10-300x211.png 300w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-9.32.10-768x540.png 768w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-9.32.10-1536x1080.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-9.32.10-2048x1440.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Navigating through the project is a joy compared to jumping through piles of code in plain text files.</p>



<p>I&#8217;ve also found having Control Sets useful, allowing me to implement the Pressed event just once for all the planets, for example.</p>



<h2 class="wp-block-heading">Roadblocks and How I Handled Them</h2>



<p>That said, I found some difficulties. All of them were due the nature of web projects. When you travel from one planet to another, you will hear an engine sound. It would be much (much!) easier to know when I should stop the sound in a Desktop or a Mobile project.</p>



<p>Having to deal with latency means I had to use a timer and guess more or less how many milliseconds is reasonable before stopping the sound. Using the same amount of time as the animation would cause the sound to continue playing after the ship had arrived at its destination, again due the latency.</p>



<p>Where I spent most of the time was optimizing the images. Specifically, delivering the images. When you play the game locally, everything works pretty fast. I found this flickering issue once I deployed the game for the first time using the custom popovers:</p>



<figure class="wp-block-video"><video height="670" style="aspect-ratio: 1276 / 670;" width="1276" controls src="https://blog.xojo.com/wp-content/uploads/2024/09/cosmic-trader-flickering-issue.mp4"></video></figure>



<p>This is something that you just don&#8217;t need to think about with the typical database application you normally build with Xojo Web. But if you build a lot of images on the fly, it will mean the browser will have to download them again and again.</p>



<p>In order to optimize it, instead of using a WebImageViewer.Image property, you could store WebImage instances. Using WebImageViewer.URL pointing to the WebImage.URL property of those instances will make the browser first check if it has downloaded that URL before. If so, bingo! It will reuse the image without having to re-download it again.</p>



<p>If you go back to the game, cache is the reason behind the &#8220;New Game&#8221; button, from the welcome screen, and the &#8220;Sell Everything&#8221; button having the same width. It wasn&#8217;t a coincidence, that means a browser cache hit.</p>



<p>Last but not least, when I shared the URL with some friends, they told me it didn&#8217;t look great on mobile. So I had to change the stats a bit so they fit in a mobile screen. While in this case it wasn&#8217;t a big deal, at Xojo we know making responsive web applications must be easier, and we will improve the workflow in future releases.</p>



<p>It would be much easier to use the Web SDK for some of those controls. If I was creating a game seriously, I&#8217;d 100% personally prefer creating some custom controls to allow some code to run on the browser side, using the Web SDK with JavaScript or TypeScript, to avoid dealing with latency or round-trips.</p>



<h2 class="wp-block-heading">Using AI for Creativity</h2>



<p>I personally don&#8217;t find any joy using AI for coding. I always end up frustrated by how it hallucinates and keep proposing, very confidently, things that just don&#8217;t exist. I understand some might like it but, in the end, I just like coding.</p>



<p>But for a second brain and helping me with (my lack of) creativity&#8230; oh boy, that&#8217;s another story. The game idea came from a conversation with Claude AI. Initially, it came up with tons of features and ideas that would require me (and a team of another 100 people) to work on it for several years. I kept asking it to simplify it until I felt it was approachable:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="415" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-10.19.09-1024x415.png" alt="" class="wp-image-13625" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-10.19.09-1024x415.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-10.19.09-300x121.png 300w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-10.19.09-768x311.png 768w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-10.19.09-1536x622.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-09-16-a-las-10.19.09.png 1768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>After implementing the game mechanics, I felt the game didn&#8217;t make any sense. I mean, why 30 turns exactly? Why 5 planets? Why can&#8217;t I go somewhere else to trade? Why do I have to trade at all?&#8230; While it is still fiction, the AI wrote a reasonable background story that added some depth to the game. That&#8217;s what you will be reading when playing Cosmic Trader.</p>



<p>No spoilers, but there are still a few features and game mechanics, recommended by the AI, that I left for future releases.</p>



<p>While working on this game, I even had a little ant invasion at home. The AI came up with a multiplayer ant colony simulator game idea that I will probably never implement, but who knows!</p>



<p>For the logo, I had some spare credits to use with DreamStudio. I had to retouch it using Affinity Photo, but that&#8217;s it:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="256" src="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-07-30-a-las-12.32.26-1024x256.png" alt="" class="wp-image-13626" srcset="https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-07-30-a-las-12.32.26-1024x256.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-07-30-a-las-12.32.26-300x75.png 300w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-07-30-a-las-12.32.26-768x192.png 768w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-07-30-a-las-12.32.26-1536x385.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/09/Captura-de-pantalla-2024-07-30-a-las-12.32.26-2048x513.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>All in all, and while a team of real humans will always be much better, I reckon AI helped me a lot with this experiment.</p>



<h2 class="wp-block-heading">Credits and Acknowledgements</h2>



<p>I could focus on building the game thanks to using the <a href="https://kenney.nl" target="_blank" rel="noreferrer noopener nofollow">Kenney game assets</a>. The background music author is <a href="https://pixabay.com/users/the_mountain-3616498/" target="_blank" rel="noreferrer noopener nofollow">Dmitrii Kolesnikov</a>, make sure to check his profile.</p>



<p>Thanks to Claude for being my second brain for this project. And, of course, thanks to Xojo. It wouldn&#8217;t be as fun without it.</p>



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



<p>I enjoyed building this project a lot. I learned things, and I fixed some bugs I found. Did you know you couldn&#8217;t add a WebStyle CSS transition without adding other styles? Me neither, but it will be fixed in Xojo 2024r3.</p>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/09/cosmic-trader-early-prototype.mp4" length="970692" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/09/cosmic-trader-current-version.mp4" length="776410" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/09/cosmic-trader-flickering-issue.mp4" length="295405" type="video/mp4" />

			</item>
		<item>
		<title>Xojo Cloud: More Than Web App Hosting</title>
		<link>https://blog.xojo.com/2024/08/15/xojo-cloud-more-than-web-app-hosting/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 15 Aug 2024 22:59:40 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[App Hosting]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Push Notifications]]></category>
		<category><![CDATA[SFTP]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Web Service]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13449</guid>

					<description><![CDATA[What better way to celebrate 10 years of Xojo Cloud than bragging about all the things it can do! When you think of Xojo Cloud,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>What better way to celebrate 10 years of Xojo Cloud than bragging about all the things it can do! When you think of Xojo Cloud, you might think that it is for hosting Xojo web apps. And that&#8217;s true, Xojo Cloud continues to be the best and easiest way to host your Xojo web apps, but Xojo Cloud also offers several useful services for other types of apps.</p>



<h2 class="wp-block-heading">iOS Notifications</h2>



<p>Xojo Cloud can function as an <a href="https://developer.apple.com/documentation/usernotifications/sending-notification-requests-to-apns">Apple Push Notification system</a> (APNs) for handling iOS push notifications. This works with Xojo and non-Xojo iOS apps. All Xojo Cloud servers are pre-configured to <a href="https://documentation.xojo.com/topics/ios/sending_and_receiving_mobile_notifications.html#topics-ios-creating-notifications-on-the-user-s-mobile-device-using-xojo-cloud-to-send-remote-notifications">send remote notifications</a>. Unlike many other cloud hosts, there is no extra charge for this feature nor is there any limit as to how many notifications you can send.</p>



<p>To send remote notifications from your iOS app you&#8217;ll need to go to the Apple Developer website to do these tasks:</p>



<ol class="wp-block-list">
<li>Add the Push Notifications feature to the App ID.</li>



<li>Generate an Apple Push Services certificate.</li>
</ol>



<p>In Xojo you need to enable the Remote Notifications entitlement for your app in the Capabilities section of the iOS Build Settings Advanced tab.</p>



<p>The final step is to upload your Push Services certificate using the Xojo Cloud control panel.</p>



<p>With super-easy access and no limits for notifications, Xojo Cloud can serve as a great APNs for handling your iOS notification needs.</p>



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



<p>Most desktop apps use a database of some kind and many are client/server database apps that talk directly to the database server. With Xojo Cloud you can host PostgreSQL or MariaDB/MySQL database servers and connect to them using an SSH tunnel for security purposes.</p>



<p>Setting up a database server on your Xojo Cloud is as easy as checking a box in the control panel.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="630" src="https://blog.xojo.com/wp-content/uploads/2024/08/image-1024x630.png" alt="" class="wp-image-13451" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/image-1024x630.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/image-300x185.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/image-768x472.png 768w, https://blog.xojo.com/wp-content/uploads/2024/08/image.png 1398w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You can turn on PostgreSQL or MySQL/MariaDB. If your Xojo Cloud server is large enough you could even do both.</p>



<p>If you want to access a database on Xojo Cloud from a desktop app, you will have to enable the SSH Tunnel and then connect to the tunnel from the computer. An SSH tunnel is a secure connection between your computer and another (in this case your Xojo Cloud server) which is used for transmitting data on a specific port. In essence, it creates a private connection through the internet which allows you to see into your server on the other end and connect to a particular service there.</p>



<p>To create a tunnel between a computer and your Xojo Cloud server, you first need to turn on the tunnel capability on your Xojo Cloud server. Go to your control panel and click the &#8220;SSH Tunnel&#8221; checkbox. You will be presented with a generated username and a password which you will use later for establishing the connection.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="694" height="302" src="https://blog.xojo.com/wp-content/uploads/2024/08/image-1.png" alt="" class="wp-image-13453" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/image-1.png 694w, https://blog.xojo.com/wp-content/uploads/2024/08/image-1-300x131.png 300w" sizes="auto, (max-width: 694px) 100vw, 694px" /></figure>



<p>On macOS and Linux, you can use a terminal command to access the tunnel (replace username and ipaddress as appropriate; you&#8217;ll be prompted for the password).</p>



<p>Use this command to tunnel to PostgreSQL:</p>



<pre class="wp-block-code"><code>ssh -L 5432:localhost:5432 username@ipaddress -N</code></pre>



<p>Use this command to tunnel to MySQL:</p>



<pre class="wp-block-code"><code>ssh -L 3306:localhost:3306 username@ipaddress -N</code></pre>



<p>If you are using Windows, you will need to use an external app such as PuTTY. There are a number of tutorials available on the internet, just put “putty ssh tunnel” into your favorite search engine.</p>



<p>With the tunnel in place you connect to the database as if it were local to the computer. This works with anything, not just Xojo apps.</p>



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



<p>Xojo Cloud offers SFTP (Secure File Transfer Protocol) for file transfer. SFTP is a secure variant of FTP which transmits files over the internet using strong encryption. That way you don&#8217;t have to worry about anyone intercepting your username and password or your files as they&#8217;re sent to or from your server.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>When choosing a client, keep in mind that SFTP is different than FTPS or FTP w/ SSL. They are not interchangeable with one another.</p>
</blockquote>



<p>Once you enable SFTP in the Control Panel, you&#8217;ll be presented with a dialog showing a generated username and password.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="447" src="https://blog.xojo.com/wp-content/uploads/2024/08/image-2-1024x447.png" alt="" class="wp-image-13454" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/image-2-1024x447.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/image-2-300x131.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/image-2-768x335.png 768w, https://blog.xojo.com/wp-content/uploads/2024/08/image-2.png 1186w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You can now connect using your favorite SFTP client. If you don&#8217;t have one, there are a number of free and paid options available including:</p>



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



<li>Transmit</li>



<li>FileZilla</li>



<li>CyberDuck</li>
</ul>



<p>Having a place to store files online is always handy and can be useful when needing to share files with others without having to rely on services such as DropBox.</p>



<h2 class="wp-block-heading">Web Services</h2>



<p>OK, a web service is technically a Xojo web app but it is really an API that is meant to be used by other apps, often desktop or mobile apps. Since a web service doesn’t have any actual UI, you don’t really need to learn how to use the majority of the Xojo Web framework.</p>



<p>Instead you basically add code to the <a href="https://documentation.xojo.com/api/web/webapplication.html#webapplication-handleurl">App.HandleURL</a> event to route web service API calls to do specific tasks and then return the results, usually as JSON for the client app to handle.</p>



<p>A web service can be a great way to consolidate code that will be used by desktop and mobile apps, for example.</p>



<p>For example, you could create a Web Service that talks to a database server (such as one of the ones available in Xojo Cloud itself). Your Desktop and Mobile apps can use the same web service to work with the database. All your database-specific code lives in the web service and the client apps make requests and display results.</p>



<p>This is a very common design pattern these days and is a necessary one if you want a mobile app to talk to a database server.</p>



<p>If you want to learn more about web services, here&#8217;s a fun webinar to check out:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Using Xojo and the Star Wars API" width="500" height="281" src="https://www.youtube.com/embed/hwhkZtP6fA8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Learn more about <a href="https://xojo.com/cloud/">Xojo Cloud</a> today. Xojo Cloud servers start at $49/month, custom servers with more RAM, storage, and virtual CPUs are available. The best way to host your Xojo web apps is so much more than just hosting web apps!</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spotlight On: LX Aer</title>
		<link>https://blog.xojo.com/2024/08/14/spotlight-on-lx-aer/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Wed, 14 Aug 2024 15:50:42 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Educational]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Spotlight On]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13446</guid>

					<description><![CDATA[Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>Spotlight On posts focus on Xojo community members. We’ll use this space to tell the stories of people using Xojo, share amazing Xojo-made apps and spread awareness of community resources. If you have an app, a project or a person you want to see featured in Spotlight On,&nbsp;<a href="mailto:hello@xojo.com" target="_blank" rel="noreferrer noopener">tell us about it</a>!</em></p>



<p>LX Aer is an AI-powered educational platform developed by student-turned-entrepreneur Leo Medvinsky. In 2020 as the pandemic forced schools to begin using remote learning tools, Leo, a student at the time, saw the gaps and the flaws in the tools he was offered and did what so many Xojo developers do, he decided to build something better. A quick view of LX Aer demonstrates it&#8217;s the solution someone who actually uses such a system would create. LX Aer is a modern take on the LMS with a user interface that centers the student and teacher. Currently, LX Aer uses Xojo Web for the backend and the project has 30,000 lines of Xojo code and growing.</p>



<h2 class="wp-block-heading">10 Questions with Leo Medvinsky of LX Aer</h2>



<h3 class="wp-block-heading">Using Xojo Web for just the backend (web services) is somewhat surprising, tell us about that?</h3>



<p>The LX Aer web app is designed to be the digital hub for students, teachers, and soon, administrators. The original web app was written in between 2020 and 2021 and used Xojo Web for some web service work but was mainly used the conventional way for Xojo Web pages. To increase speed and reliability as well as to improve performance, the decision was made that our next product (a standalone attendance tracking system) would be written using Xojo Web as a backend, with a Xojo iOS app and a standard HTML/CSS/JS web app to accompany it. We found that Xojo Web was a great way for us to have business logic on the backend, with great performance and amazing ease of management with Tim Parnell’s Lifeboat. When, in 2022, we were unifying this attendance system into the LX Aer suite, it was decided that the LX Aer suite would be combined into the attendance technology stack, rather than the other way around. This was a large time investment as it involved rewriting and rethinking significant portions of the existing product offering but has brought our software to a much stronger position.</p>



<h3 class="wp-block-heading">What is your experience with Xojo Web performance for larger scale apps like LX Aer?</h3>



<p>Up until recently, when we began self-hosting most things, we had two instances of the LX Aer Backend running on a Debian server in AWS with just 2 GB of RAM and performance was very good. We are actively developing solutions to allow for much greater scalability and distribution of load across not just instances (with Lifeboat), but across several different servers. Our database server runs CubeSQL, and Marco and I have been discussing ways to implement database sharding into CubeSQL to allow for greater scalability. While we are a startup without too many users right now, LX Aer needs to be able to support the thousands of users each school brings, along with all of their data requirements.</p>



<h3 class="wp-block-heading">Can you tell us why Xojo was chosen as the backend and what other options were ruled out?</h3>



<p>My first programming language was Visual Basic .NET. The original software I had was a simple quizzing application designed to help the user study for tests, but it could only run on Windows. This was a significant limitation. I (mostly) loved the syntax of VB compared to other languages I’ve worked with (Python, C++, Swift…), so I decided to try Xojo when I came across it in 2020. It was an <em>amazing</em> feeling to be able to write with the syntax I already knew to and make an iOS app, albeit a limited one, the same day I downloaded Xojo. Having experimented with Xojo, I started working on major projects in it very soon, and when a web development need came up, it was my go-to. Over the years, I have considered many alternatives, and many in the developer community (not Xojo’s) have discouraged me from relying on a proprietary language for such critical software, but I have never had any interest in switching. Every step of the way, Xojo has scaled with our needs.</p>



<h3 class="wp-block-heading">Mac, Windows or Linux?</h3>



<p>I flip-flop constantly between my dev machine, a Mac, and my business machine, a Surface. I tried many Linux distros on several occasions and have never been much of a fan of it as a consumer operating system.</p>



<h3 class="wp-block-heading">What do you wish more people would ask/talk to you about when it comes to LX Aer?</h3>



<p>Security. LX Aer’s tagline is “Security, Reliability, Innovation.” Notice how “security” comes first. While the Aer Intelligence<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" /> platform offers incredible AI tools built into LX Aer to improve educational outcomes, and this is one of the largest attention grabbers, I would argue that security is our most interesting innovation. Having graduated from high school just over a year ago, I recall when I found my student data leaked online after a massive breach of PupilPath, a learning management system that my school used at the time. I also recall the school I transferred to for my senior year and the software they used, Genesis, which allows a user to view their own password in plaintext after logging on. This, among other things, motivated me to always put security first. In 2023, we launched LX SecurShield<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />, which provides encryption for student data WITHOUT storing keys on the server, while still allowing a user to seamlessly log on from any device, without any of the hassle typically associated with client-side encryption. LX SecurShield<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" /> is truly unique and is something I wish more people took an interest in.</p>



<h3 class="wp-block-heading">How would you explain your most recent project to a 5-year-old?</h3>



<p>LX Aer is creating an AI chatbot that will help teachers teach and students learn!</p>



<h3 class="wp-block-heading">What&#8217;s next on your &#8220;Learn Next&#8221; list?</h3>



<p>Tough question… maybe French?</p>



<h3 class="wp-block-heading">What programming moments made you think “Wow, I love my job so much”?</h3>



<p>I’ve always been technically minded, but I have seen it as a means to an end, rather than the end itself. I never wrote code for the sake of writing code. I always had a long-term project in mind. LX Aer has been a project of mine for over 4.5 years, and has changed immensely from March 2020, when it first began. Consequently, the programming moments that made me think how much I love my job were when I was able to finally push an innovation over the edge into a working state. When I was developing LX SecurShield<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />, it required significant portions of LX Aer to be rewritten to support the new encryption. After developing a proof of concept, I worked almost nonstop for close to a week to develop it into a usable and stable state, with several all-nighters along the way. At the end of it all, I thought, “wow, I love my job so much, even with all the craziness associated with it!”</p>



<h3 class="wp-block-heading">What is something that has surprised you about coding in the last <s>10</s> 5 years?</h3>



<p>10 years ago, I was 8 and had no experience writing code <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/263a.png" alt="☺" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (though I was still the go-to tech support for my friends/family). This is a tough question, but if I had to pick it would be the difference in writing code for someone else vs. writing code for your own company. Writing code for someone else is 1,000x more difficult than writing code when you’re your own boss. As for something in the industry itself, I am always surprised by the tendency of web developers to jump around from platform to platform… Angular, React, etc. It just fascinates me.</p>



<h3 class="wp-block-heading">What is a piece of software more people should know about?</h3>



<p>To those in the Xojo community writing a web service, I cannot recommend Tim Parnell’s Lifeboat and Marco Bambini’s CubeSQL enough. To anyone working with cryptography, Björn Eiriksson’s Einhugur plugins are just incredible!&nbsp;</p>



<p>To people in general, I think it would be great if more people knew about Proton. They’re a Swiss company that develops mail, cloud storage, calendar, VPN, and password storage software, all of which uses client-side encryption and is easy-to-use. They were my inspiration for LX SecurShield<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />.&nbsp;</p>



<h3 class="wp-block-heading">What&#8217;s something you worked on recently that you are excited about?</h3>



<p>It would be somewhat cliché to say that I am excited about AI (Aer Intelligence<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />), but I am. Especially in the EdTech industry, I see so much potential for it to improve educational outcomes and make lives easier for overworked teachers.&nbsp; With our software having won the Pitchfest award at the prestigious Future of Education Technology Conference this year, I believe, largely because of our AI capabilities, I think it isn’t just the LX Aer team that’s excited about AI in education.</p>



<p>Thank you to Leo Medvinsky for answering our questions. If you want to learn more about LX Aer visit&nbsp;<a href="https://www.lxaer.com/" target="_blank" rel="noreferrer noopener">https://www.lxaer.com/</a>. To all those in the Xojo community, as a token of gratitude, Leo is offering a free license until December 31<sup>st</sup>, 2024. Email <a href="mailto:sales@lxaer.com" target="_blank" rel="noreferrer noopener">sales@lxaer.com</a> and say that you’re part of the Xojo community! &#8220;Although I have not been very active in the Xojo community in terms of engagement,&#8221; Leo says, &#8220;without the exceptionally great resource that is the Xojo Programming Forum, as well as the software and plugins made by those in the community, such as Tim Parnell, Marco Bambini, Christian Schmitz, Björn Eiriksson, and Sam Rowlands, none of this would have been possible.&#8221; See the full LX Aer Xojo community credits at <a href="https://www.lxaer.com/credits" target="_blank" rel="noreferrer noopener">https://www.lxaer.com/credits</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using a WebDataSource to Display Millions of Rows in a WebListBox</title>
		<link>https://blog.xojo.com/2024/08/01/using-a-webdatasource-to-display-millions-of-rows-in-a-weblistbox/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Thu, 01 Aug 2024 18:31:45 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[SQLiteDatabase]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WebListBox]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13373</guid>

					<description><![CDATA[If you are wondering why you would use a WebDataSource for your WebListBox, this post will give you some arguments and tips for making that decision and implementing it.]]></description>
										<content:encoded><![CDATA[
<p>If you are wondering why you would use a WebDataSource for your WebListBox, this post gives you some arguments and tips for making that decision and implementing it.</p>



<h2 class="wp-block-heading">Why would you need a WebDataSource, isn’t AddRow enough?</h2>



<p>If you are making a quick prototype, or for small data sets that won&#8217;t grow too much, yes, you can absolutely place a WebListBox into your WebPage and fill it using AddRow. If your WebListBox displays a fixed, small amount of data, say around 500~1000 rows, WebDataSource can be overkill.<br><br>However, for data that comes from a large database, it&#8217;s a different story. You could waste precious server resources duplicating the same data you have in your database into your app’s memory. And even worse, the data would be duplicated in every Session seeing that WebListBox.<br><br>In this tutorial, this is the WebListBox we are going to build:</p>



<figure class="wp-block-video"><video height="1416" style="aspect-ratio: 1368 / 1416;" width="1368" controls src="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-14.42.03.mp4.mp4"></video></figure>



<h2 class="wp-block-heading">Let’s prepare a million records database to play with.</h2>



<p>In this example we will use a humble SQLite database, but keep in mind a WebDataSource can be anything. For example you could display the result of calling an external API, or your hard drive filesystem.</p>



<p>The following SQL creates a table called “things”, with three columns: “foo”, “bar” and “baz” with one million rows:</p>



<pre class="wp-block-code"><code>CREATE TABLE things (
  id    INTEGER PRIMARY KEY AUTOINCREMENT,
  foo TEXT,
  bar TEXT,
  baz TEXT
);

-- Time to populate that table
WITH RECURSIVE cnt(x) AS 
(
   SELECT
      1 
   UNION ALL
   SELECT
      x + 1 
   FROM
      cnt LIMIT 1000000
)
INSERT INTO things (foo, bar, baz)
SELECT
    'foo_' || x AS foo,
    'bar_' || x  AS bar,
    'baz_' || x AS baz
FROM cnt;

-- Finally, let's create some indexes, so we can sort the columns quickly
CREATE INDEX "idx_foo" ON things (
    foo, id, bar, baz
);

CREATE INDEX "idx_bar" ON things (
    bar, id, foo, baz
);

CREATE INDEX "idx_baz" ON things (
    baz, id, foo, bar
);

VACUUM;</code></pre>



<p>We just need to store this SQL as a string constant, for convenience. Let’s create one, called <code>kDatabaseSetupSQLite</code> in your Application class, and paste it above the SQL code.</p>



<h2 class="wp-block-heading">First Time Setup</h2>



<p>The first time we launch the application, we need to make sure our database file has been created and populated. It won&#8217;t take too much to generate the database, but we&#8217;ll try to do it just once anyway.</p>



<p>Create a new method in your App class, called DBFile, that returns a FolderItem, pointing to the place we want to store the DataBase. Make it Public, as we will use this method later from the Session. The contents:</p>



<pre class="wp-block-code"><code>Return SpecialFolder.Desktop.Child("test-db.sqlite")</code></pre>



<p>Nothing fancy. Use another path if you want. It will be around ~200MB, just remember to delete it when you don&#8217;t need it anymore.</p>



<p>Let&#8217;s create another App method, called SetupDatabase. It will be in charge of creating and populating the database just once, so if you restart the server, the data will still be there:</p>



<pre class="wp-block-code"><code>Var db As New SQLiteDatabase
db.DatabaseFile = DBFile
db.WriteAheadLogging = True

// The file is already there, no need to build it again
If db.DatabaseFile.Exists Then
  Return
End If

db.CreateDatabase
db.Connect
db.ExecuteSQL(kDatabaseSetupSQLite)</code></pre>



<p>Lastly, implement the App.Opening event and add a method call to SetupDatabase:</p>



<pre class="wp-block-code"><code>SetupDatabase</code></pre>



<p>That should do the trick.</p>



<h2 class="wp-block-heading">Preparing the Session</h2>



<p>It&#8217;s recommended to have a Database instance for each Session. Add a new public Property to your Session class called Database of type SQLiteDatabase.</p>



<p>Then, add a handler for the Opening event with the following code:</p>



<pre class="wp-block-code"><code>Database = New SQLiteDatabase
Database.DatabaseFile = App.DBFile
Database.WriteAheadLogging = True
Database.Connect</code></pre>



<p>Every time a user arrives to the web application, a new isolated SQLiteDatabase connection will be created.</p>



<h2 class="wp-block-heading">Implementing the WebDataSource Interface</h2>



<p>Since Xojo 2024r2, the amount of methods you need in order to implement WebDataSource has been reduced.</p>



<p>Create a new class called DatabaseDataSource. Then, in the inspector panel, select the WebDataSource interface:</p>



<figure class="wp-block-video"><video height="1528" style="aspect-ratio: 2560 / 1528;" width="2560" controls src="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-11.48.19.mp4.mp4"></video></figure>



<p>This includes the three required methods: ColumnData, RowCount and RowData.</p>



<p><strong>ColumnData</strong><br>In this method, you need to return an array of <a href="https://documentation.xojo.com/api/web/weblistboxcolumndata.html#weblistboxcolumndata">WebListBoxColumnData</a>. We have four columns in this example, here is the code:</p>



<pre class="wp-block-code"><code>Var result() As WebListBoxColumnData
result.Add(New WebListBoxColumnData("ID", "id"))
result.Add(New WebListBoxColumnData("Foo", "foo"))
result.Add(New WebListBoxColumnData("Bar", "bar"))
result.Add(New WebListBoxColumnData("Baz", "baz"))

Return result</code></pre>



<p><strong>RowCount</strong><br>Xojo needs to know the amount of data your data source has. Returning an Integer is enough, but we will query our database.</p>



<pre class="wp-block-code"><code>Try
  Var rows As RowSet = Session.Database.SelectSQL("SELECT COUNT(*) AS counter FROM things")
  Return rows.Column("counter").IntegerValue
Catch DatabaseException
  Return 0
End Try</code></pre>



<p><strong>RowData</strong><br>This is the place where you need to return the row contents. As you can see, there is a rowCount and a rowOffset parameter, meaning that we won&#8217;t need to return 1 million records. The control just loads a subset. The amount is dynamically calculated, and varies depending on the height of your WebListBox and the height of the rows.</p>



<p>A sortColumns parameter is also provided. If you allow your users to sort the columns, you need to use it to know the column and direction. Fortunately, this example has sortable columns. Here is the code to comply with the WebDataSource Interface:</p>



<pre class="wp-block-code"><code>Var sql As String = "SELECT id, foo, bar, baz FROM things"
If sortColumns &lt;&gt; "" Then
  sql = sql + " ORDER BY " + sortColumns
End If
sql = sql + " LIMIT " + rowOffset.ToString + ", " + rowCount.ToString

Var result() As WebListBoxRowData
Var rows As RowSet = Session.Database.SelectSQL(sql)

// This isn't needed, it's just to demonstrate how to use cell renderers
Var style As New WebStyle
style.Bold = True
style.BackgroundColor = Color.Teal
style.ForegroundColor = Color.White

For Each row As DatabaseRow In rows
  Var newRowData As New WebListBoxRowData
  newRowData.PrimaryKey = row.Column("id").IntegerValue
  newRowData.Value("id") = row.Column("id")
  newRowData.Value("foo") = row.Column("foo")
  newRowData.Value("bar") = New WebListBoxStyleRenderer(style, row.Column("bar"))
  newRowData.Value("baz") = row.Column("baz")
  result.Add(newRowData)
Next

Return result</code></pre>



<h2 class="wp-block-heading">Preparing the User Interface</h2>



<p>You&#8217;ve reached the easiest part, building the interface takes less than a minute.</p>



<ol class="wp-block-list">
<li>Drop a DatabaseDataSource control into your WebPage</li>



<li>Drop a WebListBox control into your WebPage</li>



<li>In the WebListBox Opening event, configure the DataSource</li>
</ol>



<p>If you name your DataSource instance &#8220;MyDataSource&#8221;, this is the line of code required in the WebListBox Opening event:</p>



<pre class="wp-block-code"><code>Me.DataSource = MyDataSource</code></pre>



<p>Here is a short video:</p>



<figure class="wp-block-video"><video height="1682" style="aspect-ratio: 2800 / 1682;" width="2800" controls src="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-12.21.41.mp4.mp4"></video></figure>



<h2 class="wp-block-heading">That&#8217;s It!</h2>



<p>The WebListBox control, when combined with a WebDataSource, is a very robust and performant solution for displaying a large set of data.</p>



<p>Download the project:</p>



<div class="wp-block-file"><a id="wp-block-file--media-6f1fe487-dbb0-4d6e-a5c9-3a89f0f2fb9b" href="https://blog.xojo.com/wp-content/uploads/2024/07/weblistbox-million-rows.xojo_binary_project-1.zip">weblistbox-million-rows.xojo_binary_project</a></div>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-14.42.03.mp4.mp4" length="2629948" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-11.48.19.mp4.mp4" length="1234967" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-12.21.41.mp4.mp4" length="2146506" type="video/mp4" />

			</item>
	</channel>
</rss>
