<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Codeart — by Allan Koech]]></title><description><![CDATA[A software engineer's notes on building real systems — C++, Rust, Qt/QML, and the open-source tools that come out of the work.]]></description><link>https://www.codeart.co.ke</link><image><url>https://substackcdn.com/image/fetch/$s_!yEUh!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3da6f509-88fe-4874-9781-59a9b4b5257b_256x256.png</url><title>Codeart — by Allan Koech</title><link>https://www.codeart.co.ke</link></image><generator>Substack</generator><lastBuildDate>Mon, 29 Jun 2026 18:07:02 GMT</lastBuildDate><atom:link href="https://www.codeart.co.ke/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Allan Koech]]></copyright><language><![CDATA[en-gb]]></language><webMaster><![CDATA[allankoech@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[allankoech@substack.com]]></itunes:email><itunes:name><![CDATA[Allan Koech]]></itunes:name></itunes:owner><itunes:author><![CDATA[Allan Koech]]></itunes:author><googleplay:owner><![CDATA[allankoech@substack.com]]></googleplay:owner><googleplay:email><![CDATA[allankoech@substack.com]]></googleplay:email><googleplay:author><![CDATA[Allan Koech]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[To Port or Not to Port: C++ to Rust, and the Trap of the 90% Demo]]></title><description><![CDATA[Ownership was never in the source code. That's the whole migration &#8212; and it's exactly the part the demo skips.]]></description><link>https://www.codeart.co.ke/p/to-port-or-not-to-port-c-to-rust</link><guid isPermaLink="false">https://www.codeart.co.ke/p/to-port-or-not-to-port-c-to-rust</guid><dc:creator><![CDATA[Allan Koech]]></dc:creator><pubDate>Sun, 28 Jun 2026 21:05:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f7360ec9-5391-4901-b2e0-d0626ac198ce_1672x941.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><span>There is a demo making the rounds in every engineering org right now. You point an LLM at a gnarly C++ file, and ninety seconds later you have Rust that compiles. It looks like the migration problem just got solved. Leadership sees it, a quarter gets funded, and a team starts pointing the model at the codebase file by file.</span></p><p><span>Then, somewhere around the third month, the project stalls. Not dramatically &#8212; there&#8217;s no postmortem, no cancellation email. It just quietly stops moving. The remaining work never gets easier, the Rust never gets </span><em><span>good</span></em><span>, and eventually the branch goes stale.</span></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.codeart.co.ke/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en-gb&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Codeart &#8212; by Allan Koech! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><span>This isn&#8217;t a failure of nerve or tooling. It&#8217;s a structural property of what porting C++ to Rust actually </span><em><span>is</span></em><span> &#8212; and it&#8217;s worth understanding before you spend a quarter learning it the expensive way.</span></p><h2><strong><span>The seduction is real, and so is the wall</span></strong></h2><p><span>The reason the demo is so convincing is that the first 90% genuinely is easy now. Translating C++ control flow, arithmetic, and data structures into syntactically valid Rust is exactly the kind of pattern-matching LLMs are good at. The compiler even helps: if it builds, a lot of bugs are already gone.</span></p><p><span>The problem is what&#8217;s hiding in the last 10%, and it&#8217;s the same thing whether a human or a model is doing the work.</span></p><p><span>C++ does not encode ownership. When you write </span><code>T* p</code><span>, the language does not record whether </span><code>p</code><span> owns that memory, borrows it, shares it, or aliases something else that&#8217;s about to be freed. Those facts live in the programmer&#8217;s head, in comments, in naming conventions, and in tribal knowledge about </span><em><span>&#8220;who frees what.&#8221;</span></em><span> </span><strong><span>Rust&#8217;s entire value proposition is that these facts must be written down and checked.</span></strong><span> So a C++&#8594;Rust port is not a translation. It&#8217;s a </span><em><span>reconstruction of invariants that were never explicitly recorded.</span></em></p><div class="callout-block" data-callout="true"><p>So a C++&#8594;Rust port is not a translation. It&#8217;s a <em>reconstruction of invariants that were never explicitly recorded.</em></p></div><p><span>That&#8217;s why automatic transpilers are so instructive. Tools like </span><a href="https://arxiv.org/pdf/2511.20617"><span>c2rust</span></a><span> produce Rust that is </span><em><span>&#8220;almost always correct&#8221;</span></em><span> &#8212; and almost always </span><em><span>unsafe</span></em><span> and unidiomatic. They faithfully preserve C&#8217;s pointer semantics by wrapping everything in </span><code>unsafe</code><span>, raw pointers, and </span><code>libc</code><span> calls. The output compiles. It is also, in the words of the research, </span><em><span>&#8220;very different from the kind of Rust code usually written by humans, making it hard to read and maintain&#8221;</span></em><span> &#8212; and it sails straight past the linters that are supposed to catch the problems. You get Rust syntax with C semantics: all of the migration cost, none of the safety payoff.</span></p><p><span>LLMs improve on this &#8212; they can sometimes infer ownership and produce idiomatic code &#8212; but the failure mode is sneakier. As DARPA&#8217;s program manager for </span><a href="https://www.darpa.mil/research/programs/translating-all-c-to-rust"><span>TRACTOR </span></a><span>(the agency&#8217;s program to automate exactly this translation) put it: ask any model to translate C to safe idiomatic Rust and </span><em><span>&#8220;something comes out, and it&#8217;s often very good, but not always.&#8221;</span></em><span> When it&#8217;s not, the model tends to reach for </span><code>unsafe</code><span> to make the borrow checker stop complaining &#8212; which is precisely how you end up with code that </span><em><span>looks</span></em><span> migrated but carries the same latent bugs it always had, now harder to spot because everyone assumes </span><em><span>&#8220;it&#8217;s in Rust, so it&#8217;s safe.&#8221;</span></em></p><p><span>This is the mechanism behind the stall. The borrow checker doesn&#8217;t get tired and wave the last 10% through. Every place where the original C++ had a fuzzy ownership story becomes a hard stop that requires a human to </span><em><span>decide</span></em><span> what the ownership story should be &#8212; and frequently to redesign the data structures to express it. That&#8217;s design work, not typing work. LLMs removed the typing bottleneck, which was never the bottleneck.</span></p><h2><strong><span>The evidence cuts both ways &#8212; but cleanly</span></strong></h2><p><span>The honest read of the industry data is not </span><em><span>&#8220;Rust good&#8221;</span></em><span> or </span><em><span>&#8220;rewrites bad.&#8221;</span></em><span> It&#8217;s that </span><em><span>the shape of the project predicts the outcome</span></em><span> far better than the language choice does.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!se6i!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!se6i!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 424w, https://substackcdn.com/image/fetch/$s_!se6i!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 848w, https://substackcdn.com/image/fetch/$s_!se6i!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 1272w, https://substackcdn.com/image/fetch/$s_!se6i!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!se6i!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png" width="1456" height="375" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:375,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:158874,&quot;alt&quot;:&quot;porting strategy across the industry&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.codeart.co.ke/i/204011442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="porting strategy across the industry" title="porting strategy across the industry" srcset="https://substackcdn.com/image/fetch/$s_!se6i!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 424w, https://substackcdn.com/image/fetch/$s_!se6i!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 848w, https://substackcdn.com/image/fetch/$s_!se6i!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 1272w, https://substackcdn.com/image/fetch/$s_!se6i!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcbb153e-efa6-409f-ade6-2a8a504fb908_2536x654.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>Look at what the wins have in common. Android never </span><em><span>ported</span></em><span> anything &#8212; Google&#8217;s entire strategy is that new code is Rust and old C++ is left in place; the safety gains come from the fact that </span><em><a href="https://security.googleblog.com/2025/11/rust-in-android-move-fast-fix-things.html"><span>&#8220;most bugs live in new code&#8221;</span></a></em><span>, so you don&#8217;t need to touch the old stuff to bend the curve. Pingora wasn&#8217;t a translation at all; it was a </span><em><span>clean-room reimplementation</span></em><span> against a known spec, where the team got to design the ownership model from scratch instead of recovering it from someone else&#8217;s pointers. Mozilla picked off self-contained, parallelism-hungry components one at a time and integrated each before starting the next.</span></p><p><span>Now look at curl. Daniel Stenberg&#8217;s team spent </span><strong><span>roughly five years</span></strong><span> (2020&#8211;2025) trying to let curl use the Rust </span><a href="https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/"><span>hyper </span></a><span>library as an HTTP backend through an FFI glue layer &#8212; and ultimately ripped it out. The reasons are a near-perfect catalog of why these projects die:</span></p><ul><li><p><strong><span>The last 5% was the whole problem.</span></strong><span> </span><em><span>&#8220;The final few percent would turn out to be friction enough to now eventually make us admit defeat.&#8221;</span></em></p></li><li><p><strong><span>Nobody to do the hard part.</span></strong><span> It needed someone fluent in </span><em><span>both</span></em><span> C and Rust </span><em><span>and</span></em><span> the HTTP protocols to drive the integration across the FFI boundary &#8212; and almost no one wanted to.</span></p></li><li><p><strong><span>The FFI seam leaked.</span></strong><span> They had to </span><em><span>remove</span></em><span> HTTP/2 support because they&#8217;d misunderstood how the API integrated across the language boundary.</span></p></li><li><p><strong><span>No demand pulling it forward.</span></strong><span> curl users didn&#8217;t care that a backend was in Rust; Rust users didn&#8217;t want to maintain glue for a C project.</span></p></li></ul><p><span>Stenberg&#8217;s conclusion is the bluntest data point in the whole debate: </span><a href="https://thenewstack.io/curls-daniel-stenberg-on-securing-180000-lines-of-c-code/"><span>&#8220;We&#8217;re not going to rewrite curl in Rust. In any language &#8212; we&#8217;re not going to rewrite it at all.&#8221;</span></a><span> This from someone who openly acknowledges that </span><a href="https://daniel.haxx.se/blog/2021/03/09/half-of-curls-vulnerabilities-are-c-mistakes/"><span>roughly half of curl&#8217;s historical vulnerabilities are C memory mistakes</span></a><span>. He knows the safety case cold. He&#8217;s declining anyway, because the migration cost is real and the existing C is hardened by decades of fuzzing and CVE wrangling.</span></p><h2><strong><span>The hidden tax: comprehension debt</span></strong></h2><p><span>There&#8217;s a second-order cost that the demo never shows you, and it&#8217;s worse with LLM-driven ports than with hand ports.</span></p><p><span>When a model emits 4,000 lines of plausible Rust, </span><em><span>no one on your team owns the mental model of that code.</span></em><span> The 2025 research on LLM-generated code calls this </span><a href="https://codemanship.wordpress.com/2025/09/30/comprehension-debt-the-ticking-time-bomb-of-llm-generated-code/"><span>comprehension debt</span></a><span> and </span><em><span>&#8220;ownership debt&#8221;</span></em><span>: </span><em><span>&#8220;it compiles&#8221;</span></em><span> is not the same as </span><em><span>&#8220;someone understands why it&#8217;s correct and can change it safely.&#8221;</span></em><span> With a hand-written port, the engineer who fought the borrow checker comes out the other side </span><em><span>understanding the ownership model</span></em><span> &#8212; that understanding is half the point. With a generated port, you&#8217;ve skipped the understanding and kept only the artifact. The first time it needs a non-trivial change, you pay the comprehension cost you deferred, except now under deadline and without the person who&#8217;d have built the model.</span></p><p><span>This is why &#8220;the LLM did 90% in a week&#8221; is a misleading metric. The week of typing was never the expensive part. The expensive part is owning a correct mental model of a safety-critical system &#8212; and that&#8217;s exactly what gets skipped when the code arrives pre-written.</span></p><h2><strong><span>A decision framework that actually predicts outcomes</span></strong></h2><p><span>Stop asking </span><em><span>&#8220;should we port to Rust?&#8221;</span></em><span> It&#8217;s the wrong altitude. Ask these instead:</span></p><h3><strong><span>1. Is this new code or existing code?</span></strong></h3><p><span>If new, strongly favor Rust, and stop reading. The Android data is overwhelming: the cheapest safety win is to stop </span><em><span>adding</span></em><span> to the C++ pile. No migration risk, all the upside.</span></p><h3><strong><span>2. If existing &#8212; is the component self-contained, or is it threaded through the codebase?</span></strong></h3><p><span>A module with a narrow, well-defined interface (a parser, a codec, a proxy data path) is a Stylo/Pingora candidate. A module whose pointers reach into everything will trap you in </span><strong><span>FFI hell</span></strong><span>: every call across the C++/Rust seam is an </span><code>unsafe </code><span>boundary where Rust&#8217;s guarantees evaporate and new bugs breed. The curl/hyper failure was fundamentally an FFI-boundary failure.</span></p><h3><strong><span>3. Do you have a spec, or only the code?</span></strong></h3><p><span>If you can reimplement against a specification or a strong test suite (Pingora had the HTTP spec; you can have a differential test harness), favor a </span><em><span>clean-room rewrite</span></em><span> over a line-by-line port. You&#8217;ll design the ownership model instead of reverse-engineering it, and you can run old and new side by side to prove equivalence.</span></p><h3><strong><span>4. Will someone own the result?</span></strong></h3><p><span>If the answer is </span><em><span>&#8220;the LLM wrote it and we&#8217;ll figure it out later,&#8221;</span></em><span> you don&#8217;t have a migration plan, you have a future incident. Budget the human comprehension cost up front or don&#8217;t start.</span></p><h3><strong><span>5. Is the existing C++ actually your risk?</span></strong></h3><p><span>Battle-hardened, heavily-fuzzed C++ that hasn&#8217;t thrown a CVE in years is not where your memory-safety risk concentrates. New and frequently-changed code is. Spend the migration budget where the bugs actually are.</span></p><h2><strong><span>The verdict</span></strong></h2><p><strong><span>Use the LLM</span></strong><span>. It genuinely removed a real cost &#8212; the mechanical translation that used to make these projects unaffordable to even start. But understand precisely what it removed and what it didn&#8217;t. It removed the </span><em><span>typing</span></em><span>. It did not remove the </span><em><span>thinking</span></em><span>: recovering ownership invariants that C++ never recorded, designing data structures that satisfy the borrow checker, and proving the result is equivalent to the original.</span></p><p><strong><span>That thinking is the project</span></strong><span>. It was always the project. The reason ports stall at 90% is that the demo completes the 90% that was never hard, and then hands you the 10% that was the entire point &#8212; now disguised as &#8220;almost done.&#8221;</span></p><p><strong><span>Port new code by default</span></strong><span>. Port self-contained components against a spec. Leave hardened, stable C++ alone. And treat any plan whose timeline is built on </span><em><span>&#8220;the model already wrote most of it&#8221;</span></em><span> as a plan that hasn&#8217;t started yet.</span></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.codeart.co.ke/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en-gb&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Codeart &#8212; by Allan Koech! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[MantisBase is Moving to Rust]]></title><description><![CDATA[There is no shortage of "rewrite it in Rust" stories on the internet.]]></description><link>https://www.codeart.co.ke/p/mantisbase-is-moving-to-rust</link><guid isPermaLink="false">https://www.codeart.co.ke/p/mantisbase-is-moving-to-rust</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Mon, 18 May 2026 19:40:05 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/aaa6e839-a98a-4cd7-a7f7-9dd0bdbf4142_690x350.svg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IXjp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IXjp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 424w, https://substackcdn.com/image/fetch/$s_!IXjp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 848w, https://substackcdn.com/image/fetch/$s_!IXjp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 1272w, https://substackcdn.com/image/fetch/$s_!IXjp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IXjp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IXjp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 424w, https://substackcdn.com/image/fetch/$s_!IXjp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 848w, https://substackcdn.com/image/fetch/$s_!IXjp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 1272w, https://substackcdn.com/image/fetch/$s_!IXjp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fc8da7-12f5-498d-8934-d20d96346e38_690x350.svg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>There is no shortage of <em>"rewrite it in Rust"</em> stories on the internet. Some are driven by hype, others by genuine engineering needs. This is not the former. What follows is a straightforward account of where MantisBase is headed, why, and what it means for you.</p><div><hr></div><h2>A Growing Ecosystem Worth Taking Seriously</h2><p>Before getting into the decision itself, it is worth acknowledging the state of Rust as a language and ecosystem. The <em>Rustacean</em> community has grown into one of the most active and technically rigorous developer communities in open source. The <a href="https://crates.io">crates.io</a> registry now hosts hundreds of thousands of packages, covering everything from async runtimes and HTTP frameworks to database drivers, JWT handling, and mailer integrations &#8212; all with first-class tooling and consistently high quality. Rust has also topped Stack Overflow's "most admired language" survey for several consecutive years, which speaks less to popularity and more to developer satisfaction once they have committed to it.</p><p>We have been watching this ecosystem closely. It has matured to a point where building a production-grade, single-binary backend on top of it is not only feasible &#8212; it is arguably the most sensible path forward for a project with MantisBase's goals.</p><div><hr></div><h2>What Is Already Happening</h2><p>Work on v0.4 has begun, and it is a full rewrite in Rust. The goal is to reach feature parity with the current C++ release at minimum, and to go further where the new foundation makes it practical to do so. If you want to track progress, the <a href="https://github.com/allankoechke/mantisbase">master branch on GitHub</a> already reflects the active rewrite &#8212; the repository is already building and running in Rust, with core functionality like entity schemas, REST routing, access rules, JWT authentication, admin dashboard serving, and webhook support already in place.</p><p>This is not a distant roadmap item. It is ongoing work, and it is further along than most announcements of this kind tend to let on.</p><div><hr></div><h2>Why the C++ Foundation Was Holding Us Back</h2><p>MantisBase started as a C++ project for good reasons: raw speed, embeddability, and a single-binary deployment model with no external runtime dependency. Those goals have not changed. What changed is our assessment of the cost of continuing to pursue them in C++.</p><p>The C++ codebase accumulated a set of challenges over time &#8212; not insurmountable, but expensive to address correctly. Memory management patterns that required careful audit, integration complexity when pulling in third-party libraries, and a build system that made certain kinds of cross-platform testing harder than it needed to be. Fixing these properly would have demanded a significant investment of time &#8212; time that should have gone toward improving the product.</p><p>The practical result was that several things we wanted to deliver kept getting pushed back. The documentation site needed modernisation. The admin dashboard needed a cleaner, more capable UI. The REST API had features we wanted to expand. Most notably, out-of-the-box SDK support for JavaScript and Python &#8212; something users have asked about consistently &#8212; was hard to prioritise while we were managing the overhead of the C++ foundation.</p><p>We reached a point where the honest assessment was: the language itself had become a constraint on the project's growth, not just a technical detail.</p><div><hr></div><h2>Why Rust, and Not Zig or Go</h2><p>Once the decision to move away from C++ was made, we evaluated the realistic alternatives that could preserve what made MantisBase useful in the first place: a single compiled binary, genuine performance, and low memory overhead. Rust, Zig, and Go were the serious contenders.</p><p>Go produces clean binaries and has an excellent standard library, but its garbage collector introduces latency characteristics that are a poor fit for a backend meant to be embedded inside other applications. Zig is technically compelling and offers tight control over memory, but its ecosystem and tooling are still maturing &#8212; pulling in third-party integrations would mean building more from scratch than we wanted.</p><p>Rust offered the right combination: compile-time memory safety without a garbage collector, a mature ecosystem through crates.io, and tooling (cargo, rustfmt, clippy, cargo test) that genuinely reduces friction rather than adding to it. The memory safety story was particularly relevant. Part of why the C++ codebase was difficult to maintain was precisely the category of issues that Rust eliminates at the compiler level &#8212; use-after-free, data races, invalid pointer dereferences. We could have audited and hardened the C++ code, but choosing Rust means we do not have to keep having that conversation on every future contribution.</p><p>Beyond safety, the crate ecosystem makes it straightforward to integrate capabilities that previously required significant custom work: mailer support via <a href="https://github.com/lettre/lettre">lettre</a>, async HTTP with <a href="https://github.com/tokio-rs/axum">axum</a>, database access via <a href="https://github.com/launchbargain/sqlx">sqlx</a>, and more. These are not afterthoughts &#8212; they are well-maintained, widely used libraries that slot in cleanly.</p><p>First-class test support via <code>cargo test</code> is also worth naming directly. Writing and running tests in C++ projects of this kind involves considerably more ceremony. In Rust, testing is a natural part of the workflow, which matters when you are trying to build confidence in a rewrite incrementally.</p><div><hr></div><h2>Language SDK Support Becomes Realistic</h2><p>One of the things we wanted to offer from early on was MantisBase SDKs for JavaScript and Python &#8212; not just REST clients, but deeper integration. In the C++ world, producing idiomatic bindings for both languages meant navigating complex FFI boundaries, separate build pipelines, and significant maintenance surface.</p><p>From Rust, this is substantially more tractable. The <a href="https://pyo3.rs">PyO3</a> project provides a mature path for exposing Rust libraries to Python, and <a href="https://neon-bindings.com">Neon</a> (or WASM targets) covers the Node.js side. We are not committing to a specific release timeline for these yet, but the rewrite removes the structural obstacle that made them impractical before.</p><div><hr></div><h2>What Happens to C++ Support</h2><p>The original C++ releases are not being abandoned. Binaries up through v0.3.5 remain available on the <a href="https://github.com/allankoechke/mantisbase/releases">GitHub releases page</a>, and that code is not going anywhere.</p><p>Looking further ahead, we are interested in the model that projects like <a href="https://slint.dev">Slint</a> have demonstrated. Slint is a UI toolkit written in Rust that exposes a fully supported C++ API &#8212; developers working in C++ interact with it as though it were a native C++ library, with no Rust toolchain required on their end. Several other projects in the embedded and systems space have taken similar approaches. We are examining what that looks like for MantisBase's embedding use case, and C++ API support remains part of the long-term plan.</p><div><hr></div><h2>What to Expect Next</h2><p>The v0.4 work is progressing in the open. You can follow along, open issues, or contribute via the <a href="https://github.com/allankoechke/mantisbase">GitHub repository</a>. The current Rust codebase is already functional enough to run and experiment with.</p><p>A more detailed devlog covering the architecture of the Rust port &#8212; including database abstraction, the new schema engine, and the HTTP layer &#8212; is coming soon. For updates, subscribe below or follow <a href="https://x.com/allankoechke">@allankoechke</a> on X.</p><div><hr></div><p><em>MantisBase is an open-source, single-binary Backend-as-a-Service. Visit <a href="https://mantisbase.com">mantisbase.com</a> for documentation and demos.</em></p>]]></content:encoded></item><item><title><![CDATA[What’s new in 3ds Max 2027?]]></title><description><![CDATA[Originally posted here:]]></description><link>https://www.codeart.co.ke/p/whats-new-in-3ds-max-2027</link><guid isPermaLink="false">https://www.codeart.co.ke/p/whats-new-in-3ds-max-2027</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Mon, 13 Apr 2026 07:25:40 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/4f517473-944d-4277-9db7-47c37427c948_1412x795.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gEzp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gEzp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 424w, https://substackcdn.com/image/fetch/$s_!gEzp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 848w, https://substackcdn.com/image/fetch/$s_!gEzp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 1272w, https://substackcdn.com/image/fetch/$s_!gEzp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gEzp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gEzp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 424w, https://substackcdn.com/image/fetch/$s_!gEzp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 848w, https://substackcdn.com/image/fetch/$s_!gEzp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 1272w, https://substackcdn.com/image/fetch/$s_!gEzp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6d49560-3af5-4f88-8d9a-7638a5343edc_1412x795.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><div><hr></div><p>Originally posted here:</p><blockquote><h4><a href="https://blog.autodesk.io/whats-new-in-3ds-max-2027/">Explore New Features in 3ds Max 2027 Release Updates</a></h4></blockquote><div><hr></div><p>A few weeks ago, 3ds Max 2027 was officially released, introducing new features and capabilities for both artists and developers. With this release, 3ds Max saw many upgrades including <em>Arnold to 5.9.0, USD to 0.14.0, Substance to 3.0.6</em>, performance improvements across tools, modifiers, and render workflows, and much more. Refer to the <a href="https://help.autodesk.com/view/3DSMAX/2027/ENU/?guid=GUID-7CC2F041-F797-4DB9-B2F9-326AAB994F37">product release page</a> for a detailed feature breakdown for 3ds Max 2027.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 424w, https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 848w, https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 1272w, https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 1456w" sizes="100vw"><img src="https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif" width="800" height="450" data-attrs="{&quot;src&quot;:&quot;https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:450,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Smart Bevel for post-Boolean intersections&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Smart Bevel for post-Boolean intersections" title="Smart Bevel for post-Boolean intersections" srcset="https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 424w, https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 848w, https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 1272w, https://blog.autodesk.io/wp-content/uploads/2026/04/GUID-05B7B772-F025-42E4-A43B-238EE14FDF74.gif 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Smart Bevel for post-Boolean intersections released in 3ds Max 2027</figcaption></figure></div><h2>New Features, Improvements, and Updated Workflows</h2><p>3ds Max 2027 ships with several notable updates across its plugin ecosystem:&nbsp;</p><ul><li><p>Arnold for 3ds Max updated to <em>5.9.0</em> (Arnold <em>7.5.0.0</em>)</p></li><li><p>USD for 3ds Max updated to <em>0.14.0</em></p></li><li><p>Substance updated to 3.0.6</p></li><li><p>Autodesk Assistant (Technical Preview): An AI-powered tool that helps you quickly find information about features and workflows directly within the product &#8212; a welcome addition for developers and artists alike looking to streamline their pipeline research. Read more <a href="https://help.autodesk.com/view/3DSMAX/2027/ENU/?guid=GUID-92EF3530-9E04-46DF-B3F2-2BA150C6CEDF">here</a>.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DtIv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DtIv!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 424w, https://substackcdn.com/image/fetch/$s_!DtIv!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 848w, https://substackcdn.com/image/fetch/$s_!DtIv!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 1272w, https://substackcdn.com/image/fetch/$s_!DtIv!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DtIv!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif" width="1280" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A digital interface displaying guidelines for camera types in 3ds Max 2026, set in a kitchen environment with chairs and a fridge in the background.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A digital interface displaying guidelines for camera types in 3ds Max 2026, set in a kitchen environment with chairs and a fridge in the background." title="A digital interface displaying guidelines for camera types in 3ds Max 2026, set in a kitchen environment with chairs and a fridge in the background." srcset="https://substackcdn.com/image/fetch/$s_!DtIv!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 424w, https://substackcdn.com/image/fetch/$s_!DtIv!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 848w, https://substackcdn.com/image/fetch/$s_!DtIv!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 1272w, https://substackcdn.com/image/fetch/$s_!DtIv!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281cee7a-03a4-4099-ae60-7cffff8e7412_1280x720.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>SDK Changes</h2><p>Now let's get into what matters most for plugin developers.</p><ul><li><p><strong>.NET 10.0 Support</strong>: 3ds Max 2027 moves plugin development to .NET 10. Note that .NET 8, introduced in 3ds Max 2026, has reached an end of life and is no longer supported. If you are still on an older version, refer to our porting guide from .NET Framework to .NET for plugins for step-by-step migration guidance.</p></li><li><p><strong>DirectX 9 Removal</strong>: Support for DirectX 9 has been fully removed. This affects several headers that have been dropped from the public SDK &#8212; notably id3d9graphicswindow.h, idx9pixelshader.h, and idx9vertexshader.h &#8212; along with related interfaces in <em>ihardwarematerial.h, ihardwarerender.h, </em>and <em>RTMax.h</em>. Developers relying on these should migrate to the DirectX 11 equivalents now available in the SDK.</p></li><li><p><strong>Updated Core Dependencies</strong>: 3ds Max 2027 development specifies Visual Studio 2022 (v17.14.x), C++20, Qt 6.8.3. Review your plugin dependencies against these versions before building. You could also use the newer Visual Studio 2026, when you set the toolset to be v143.</p></li><li><p><strong>API Changes</strong>: There are targeted API updates across several headers &#8212; including new methods in <em>custcont.h</em>,<em> ioapi.h</em>, and<em> IValidateNodeCallback.h</em>, as well as deprecations in <em>object.h</em>, <em>gfx.h</em>, and others.</p></li><li><p><strong>Updated Samples and Documentation</strong>: Samples and documentation have been updated to reflect all API changes in this release.</p></li></ul>]]></content:encoded></item><item><title><![CDATA[MantisBase v0.3.4 — Admin Upgrades, Bug Fixes & Docker Updates]]></title><description><![CDATA[We're shipping v0.3.4 today with a handful of quality-of-life improvements, a cleaner configuration story, and a few important bug fixes.]]></description><link>https://www.codeart.co.ke/p/mantisbase-v0-3-4-release</link><guid isPermaLink="false">https://www.codeart.co.ke/p/mantisbase-v0-3-4-release</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Thu, 26 Feb 2026 23:24:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d102db5a-65ce-48ca-9db4-94fbd04d1d0b_1920x1080.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K04a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K04a!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!K04a!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!K04a!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!K04a!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K04a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!K04a!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!K04a!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!K04a!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!K04a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcca9d511-1d33-49f6-9a3c-f970fb442a10_1920x1080.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>We're shipping <em><strong>v0.3.4</strong></em> today with a handful of quality-of-life improvements, a cleaner configuration story, and a few important bug fixes. Here's what's new.</p><div><hr></div><h2>Unified <code>MB_*</code> Environment Variable Prefix</h2><p>All environment variables now consistently use the <code>MB_*</code> prefix. If you were previously setting <code>MANTIS_JWT_SECRET</code>, update that to <code>MB_JWT_SECRET</code> &#8212; the old name is no longer recognised. This brings every runtime knob under one coherent namespace and makes it easier to manage configuration in Docker and CI environments.</p><p>Variable Description Default <code>MB_JWT_SECRET</code> JWT signing secret (set this in production!) built-in default <code>MB_DISABLE_FILE_UPLOADS</code> Set to <code>1</code> to disable file uploads globally <code>0</code> <code>MB_DISABLE_ADMIN_ON_FIRST_BOOT</code> Set to <code>1</code> to skip auto-admin creation browser spin off <code>0</code> <code>MB_DISABLE_RATE_LIMIT</code> Set to <code>1</code> to disable rate limiting enabled</p><div><hr></div><h2>File Upload Kill Switch</h2><p>A new <code>MB_DISABLE_FILE_UPLOADS=1</code> flag lets you turn off file uploads at the server level without touching your schema. Any upload attempt while this flag is active will receive a <code>403 Forbidden</code> response. Useful for read-only deployments or environments where you want to enforce that no files land on disk.</p><div><hr></div><h2>Docker Improvements</h2><p>The Dockerfile has been updated to <code>debian:trixie-slim</code> as its base, and the build arg has been renamed from <code>MANTIS_VERSION</code> to <code>MB_VERSION</code> (default <code>0.3.4</code>) to match the new naming convention. The docker-compose file now also surfaces all <code>MB_*</code> variables as commented-out stubs, so it's clear what you can configure without digging through docs.</p><p>The published image on Docker Hub is <code>allankoech/mantisbase</code> &#8212; the quick-start command is simply:</p><pre><code>docker run -p 7070:80 allankoech/mantisbase
</code></pre><p>All submodules have also been switched from SSH to HTTPS URLs and set to shallow fetch, which significantly speeds up fresh clones in CI pipelines.</p><div><hr></div><h2>Admin Panel Updates</h2><p>Several improvements have landed in the admin UI this release:</p><p><strong>Entity cloning</strong> &#8212; You can now clone an existing entity directly from the admin panel. Cloning copies the source entity's schema (field names, types, and structure) into a new entity, giving you a clean starting point to build on without recreating common field sets from scratch. No records are carried over, only the schema.</p><p><strong>Entity renaming</strong> &#8212; Entities can now be renamed from within the admin panel without having to drop and recreate them.</p><p><strong>Long entity name overflow fix</strong> &#8212; Entity names that exceeded the available sidebar/panel width were pushing other UI elements off screen. This has been corrected so long names truncate gracefully and the layout stays intact.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dyiE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dyiE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 424w, https://substackcdn.com/image/fetch/$s_!dyiE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 848w, https://substackcdn.com/image/fetch/$s_!dyiE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 1272w, https://substackcdn.com/image/fetch/$s_!dyiE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dyiE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png" width="556" height="366" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:366,&quot;width&quot;:556,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!dyiE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 424w, https://substackcdn.com/image/fetch/$s_!dyiE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 848w, https://substackcdn.com/image/fetch/$s_!dyiE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 1272w, https://substackcdn.com/image/fetch/$s_!dyiE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a3e558d-7a68-414b-a74f-3d95b0d10f5d_556x366.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Minor bug fixes and improvements</strong> across the admin panel generally.</p><div><hr></div><h2>Bug Fixes</h2><ul><li><p><strong>PATCH requests with password fields</strong> &#8212; a missing-field error that surfaced when patching records containing a <code>password</code> field has been resolved.</p></li><li><p><strong>Last-activity tracking</strong> &#8212; activity timestamps now only update on actual database record changes, not on every SSE ping or passive connection event. This prevents misleading "active" signals for idle clients.</p></li><li><p><strong>SSE session cleanup</strong> &#8212; auth tokens are no longer held in memory on SSE sessions. The token field is explicitly nulled out after verification, reducing the risk of credentials lingering in heap memory across a long-lived connection.</p></li></ul><div><hr></div><h2>Internal / Code Quality</h2><ul><li><p><code>soci_wrappers.h</code> saw a significant cleanup &#8212; redundant nesting in the field-binding logic was flattened, making the type-dispatch code considerably easier to follow.</p></li><li><p>SSE event queuing now uses <code>emplace</code> instead of <code>push</code> for slightly cleaner construction.</p></li><li><p>SQL update column formatting moved to <code>std::format</code> for consistency.</p></li></ul><div><hr></div><h2>Upgrading</h2><p>Update your environment variables from <code>MANTIS_JWT_SECRET</code> &#8594; <code>MB_JWT_SECRET</code> and pull the new image or rebuild from source. No schema migrations are required for this release.</p><p>The full changelog and binaries are available on the <a href="https://github.com/allankoechke/mantisbase/releases/tag/v0.3.4">GitHub releases page</a>.</p>]]></content:encoded></item><item><title><![CDATA[MantisBase Devlog #1—We're Live]]></title><description><![CDATA[If you've been following along, you know I've been busy building MantisBase for a while now.]]></description><link>https://www.codeart.co.ke/p/mb-devlog1-landing-page</link><guid isPermaLink="false">https://www.codeart.co.ke/p/mb-devlog1-landing-page</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Thu, 26 Feb 2026 20:24:07 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7abe0891-406b-4d16-acb6-41a56d758e80_1920x1080.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5BRd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5BRd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!5BRd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!5BRd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!5BRd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5BRd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5BRd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!5BRd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!5BRd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!5BRd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c2d4df6-27c7-4e50-a1fd-dac9655aac48_1920x1080.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>If you've been following along, you know I've been busy building <a href="https://github.com/allankoech/mantisbase">MantisBase</a> for a while now. Today feels like a good checkpoint to step back, write a bit, and share what's shipped.</p><p>This is the first official devlog. There will be more.</p><div><hr></div><h2>The Project Website is Up</h2><p>First things first, MantisBase now has a proper home on the internet.</p><blockquote><h4><a href="https://mantisbase.com">MantisBase | Lightning fast BaaS in C++</a></h4></blockquote><p>It's a landing page for now, but it does the job &#8212; gives you a quick feel for what MantisBase is and where it's headed. If you've been curious but haven't dug into the GitHub repo yet, the website is probably the gentler starting point.</p><div><hr></div><h2>Try It Without Installing Anything</h2><p>This one I'm particularly happy about.</p><p>One of the biggest friction points with any self-hosted tool is the "I'll check it out later" trap; you bookmark it, tell yourself you'll spin it up over the weekend, and then never do. I've been guilty of this myself more times than I'd like to admit.</p><p>So we now have a live demo environment:</p><blockquote><h4><a href="https://demo.mantisbase.com">Mantis Admin Dashboard</a></h4></blockquote><p>No installation. No Docker. No config files. Just open it and poke around. If it clicks for you, <em>then</em> you can go down the setup rabbit hole.</p><div><hr></div><h2>Docker Image on Docker Hub</h2><p>Speaking of setup&#8212;for those who are comfortable with Docker and just want to pull and run, we've got you covered.</p><pre><code>docker pull allankoech/mantisbase
</code></pre><p>Full image available at:</p><blockquote><h4><a href="https://hub.docker.com/r/allankoech/mantisbase">allankoech/mantisbase - Docker Image</a></h4></blockquote><p>This is probably the fastest path from zero to a running instance if you're on a server or just want to keep things clean on your local machine.</p><div><hr></div><h2>What's Next</h2><p>We're currently in the middle of cleaning up the admin UI &#8212; ironing out some rough edges and squashing a few bugs that have been on the list. Nothing dramatic, just the kind of polish work that makes the difference between something that <em>works</em> and something that feels <em>solid</em>.</p><p>More updates soon. If you want to follow along, the <a href="https://github.com/allankoech/mantisbase">GitHub repo</a> is the most up-to-date place to track progress.</p><p>Until the next devlog. &#9996;&#65039;</p>]]></content:encoded></item><item><title><![CDATA[MantisBase v0.3.3: Real-Time Database Updates with Server-Sent Events]]></title><description><![CDATA[February 4, 2026 &#8212; We're excited to announce the release of MantisBase v0.3.3, bringing real-time database capabilities to this lightweight, high-performance Backend-as-a-Service framework.]]></description><link>https://www.codeart.co.ke/p/mantisbase-v0_3_3-rtdb</link><guid isPermaLink="false">https://www.codeart.co.ke/p/mantisbase-v0_3_3-rtdb</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Tue, 03 Feb 2026 22:04:45 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/81d7baa2-da37-44c7-b207-6efa851b3ba1_1920x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jJqT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jJqT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!jJqT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!jJqT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!jJqT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jJqT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jJqT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!jJqT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!jJqT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!jJqT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4458d63-b839-4549-89ce-f6b1618f0c96_1920x1080.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">MantisBase version 0.3.3 release banner featuring real-time database updates with Server-Sent Events support</figcaption></figure></div><p><strong>February 4, 2026</strong> &#8212; We're excited to announce the release of MantisBase v0.3.3, bringing real-time database capabilities to this lightweight, high-performance Backend-as-a-Service framework. This release introduces Server-Sent Events (SSE) support for both SQLite and PostgreSQL backends, along with critical bug fixes and improved system observability.</p><h2>What's New in v0.3.3</h2><h3>Real-Time Database via SSE</h3><p>The flagship feature of <em>v0.3.3</em> is native real-time database synchronisation using Server-Sent Events. Unlike traditional polling approaches that waste resources checking for updates, SSE establishes a persistent HTTP connection that allows the server to push changes to clients as they happen.</p><p><strong>Why SSE?</strong></p><p>Server-Sent Events offer several advantages for real-time database applications:</p><ul><li><p><strong>Efficient unidirectional streaming</strong> &#8212; Perfect for database change notifications where data flows primarily from server to client</p></li><li><p><strong>Built on standard HTTP</strong> &#8212; No special protocols or WebSocket infrastructure required</p></li><li><p><strong>Automatic reconnection</strong> &#8212; The browser's EventSource API handles connection recovery automatically</p></li><li><p><strong>Firewall-friendly</strong> &#8212; Works through corporate proxies and firewalls that might block WebSocket connections</p></li><li><p><strong>Low overhead</strong> &#8212; Simpler than WebSockets when you don't need bidirectional communication</p></li></ul><h3>Universal Backend Support</h3><p>Real-time updates now work seamlessly with both SQLite and PostgreSQL databases. Whether you're running MantisBase on an embedded device with SQLite or scaling up with PostgreSQL, you get the same real-time capabilities without changing your code.</p><h3>Enhanced System Observability</h3><p>System logs have been moved to a dedicated database and are now accessible through the <code>/api/v1/logs</code> endpoint, providing administrators with powerful filtering and pagination capabilities for monitoring and debugging.</p><h2>Getting Started with Real-Time</h2><h3>Opening an SSE Connection</h3><p>Connect to the real-time endpoint and subscribe to entity changes:</p><pre><code>// Subscribe to changes on the 'posts' entity
const eventSource = new EventSource(
  'http://localhost:7070/api/v1/realtime?topics=posts'
);

// Listen for all events
eventSource.onmessage = (event) =&gt; {
  const data = JSON.parse(event.data);
  console.log('Received event:', data);
};

// Handle connection events
eventSource.onopen = () =&gt; {
  console.log('SSE connection established');
};

eventSource.onerror = (error) =&gt; {
  console.error('SSE connection error:', error);
  // Browser automatically reconnects
};
</code></pre><h3>Subscribing to Multiple Entities</h3><p>You can monitor multiple database entities on a single connection:</p><pre><code>// Subscribe to posts, comments, and users
const eventSource = new EventSource(
  'http://localhost:7070/api/v1/realtime?topics=posts,comments,users'
);

eventSource.onmessage = (event) =&gt; {
  const data = JSON.parse(event.data);
  
  // Events include the entity name they originated from
  switch(data.entity) {
    case 'posts':
      updatePostsUI(data);
      break;
    case 'comments':
      updateCommentsUI(data);
      break;
    case 'users':
      updateUsersUI(data);
      break;
  }
};
</code></pre><h3>Event Format</h3><p>Real-time events follow a consistent JSON structure:</p><pre><code>{
  "type": "INSERT",
  "entity": "posts",
  "data": {
    "id": "abc123",
    "title": "New Post Title",
    "content": "Post content here",
    "created": "2026-02-03T14:30:00Z",
    "updated": "2026-02-03T14:30:00Z"
  },
  "timestamp": "2026-02-03T14:30:00.123Z"
}
</code></pre><p><strong>Event Types:</strong></p><ul><li><p><code>INSERT</code> &#8212; New record created</p></li><li><p><code>UPDATE</code> &#8212; Existing record modified</p></li><li><p><code>DELETE</code> &#8212; Record removed</p></li></ul><h3>Dynamic Topic Management</h3><p>Update your subscriptions without reconnecting:</p><pre><code>// Later, add more topics to the existing connection
async function subscribeToComments() {
  await fetch('http://localhost:7070/api/v1/realtime', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${yourAuthToken}`
    },
    body: JSON.stringify({
      client_id: clientId,
      topics: ['posts', 'comments']  // Updated topic list
    })
  });
}

// Or clear all subscriptions
async function unsubscribeAll() {
  await fetch('http://localhost:7070/api/v1/realtime', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${yourAuthToken}`
    },
    body: JSON.stringify({
      client_id: clientId,
      topics: []  // Empty array clears all topics
    })
  });
}
</code></pre><h2>System Logs API</h2><p>Access and monitor system logs with the new logs endpoint:</p><pre><code># Get recent logs (requires admin authentication)
curl -H "Authorization: Bearer &lt;admin_token&gt;" \
  http://localhost:7070/api/v1/logs

# Filter by log level
curl -H "Authorization: Bearer &lt;admin_token&gt;" \
  "http://localhost:7070/api/v1/logs?level=ERROR"

# Pagination
curl -H "Authorization: Bearer &lt;admin_token&gt;" \
  "http://localhost:7070/api/v1/logs?limit=50&amp;offset=100"

# Filter by time range
curl -H "Authorization: Bearer &lt;admin_token&gt;" \
  "http://localhost:7070/api/v1/logs?from=2026-02-03T00:00:00Z&amp;to=2026-02-03T23:59:59Z"
</code></pre><h2>Migration Guide</h2><p>If you're upgrading from <em>v0.3.2</em>, here's what you need to know:</p><h3>Breaking Changes</h3><p>There are no breaking changes in <em>v0.3.3</em>. The real-time API is a new addition that doesn't affect existing functionality. To enrol existing entities to be real-time "enabled", update the entities to trigger the real-time monitoring.</p><h3>Security Considerations</h3><h3>Authentication for Real-Time</h3><p>Real-time connections respect MantisBase's access control rules:</p><ul><li><p>For public topics (entities), no additional authentication is required.</p></li><li><p>For non-public entities, the following rules are enforced:</p><ul><li><p><em>List Rule</em>: Used to list records in an entity.</p></li><li><p><em>Get Rule</em>: Used to fetch a record by the record ID.</p></li></ul></li></ul><p>For non-public entities, provide the authorisation <strong>JWT</strong> token when creating the <code>EventSource</code> stream.</p><h2>Installation &amp; Upgrade</h2><h3>Download Pre-built Binaries</h3><p>Download the latest release from <a href="https://github.com/allankoechke/mantisbase/releases/tag/v0.3.3">GitHub Releases</a>:</p><pre><code># Linux
wget https://github.com/allankoechke/mantisbase/releases/download/v0.3.3/mantisbase-linux-x64.zip
unzip mantisbase-linux-x64.zip
chmod +x mantisbase
./mantisbase serve

# Windows
# Download mantisbase-windows-x64.zip and extract
mantisbase.exe serve
</code></pre><h3>Build from Source</h3><pre><code>git clone --recurse-submodules https://github.com/allankoechke/mantisbase.git
cd mantisbase
git checkout v0.3.3
cmake -B build
cmake --build build
./build/mantisbase serve
</code></pre><h3>Bug Fixes</h3><p>This release includes several important bug fixes:</p><ul><li><p>Fixed memory leak in SSE connection handling</p></li><li><p>Improved database connection pooling for PostgreSQL</p></li><li><p>Resolved race condition in concurrent entity updates</p></li><li><p>Fixed authentication token refresh timing</p></li><li><p>Corrected <em><strong>CORS</strong></em> headers for cross-origin real-time connections</p></li></ul><h2>Community &amp; Support</h2><p>Join our growing community:</p><ul><li><p><strong>GitHub</strong>: <a href="https://github.com/allankoechke/mantisbase">github.com/allankoechke/mantisbase</a></p></li><li><p><strong>Documentation</strong>: <a href="https://allankoechke.github.io/mantisbase/">allankoechke.github.io/mantisbase</a></p></li><li><p><strong>YouTube Tutorials</strong>: <a href="https://youtube.com/playlist?list=PLsG0sKNmNpyQwsZuReuqo_nl_j4SdJoiJ">MantisBase Playlist</a></p></li><li><p><strong>Discussions</strong>: <a href="https://github.com/allankoechke/mantisbase/discussions">GitHub Discussions</a></p></li><li><p><strong>Support</strong>: <a href="https://patreon.com/allankoech">Patreon</a></p></li></ul><h2>Acknowledgments</h2><p>Thank you to everyone who contributed to this release through bug reports, feature requests, and code contributions. MantisBase is built for developers, by developers.</p><div><hr></div><p>Checkout the video announcement here:</p><div class="captioned-image-container"><figure><div id="youtube2-M6pJJEILPv0" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;M6pJJEILPv0&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/M6pJJEILPv0?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div></figure></div><div><hr></div><p><strong>MantisBase</strong>&#8212;Lightning-fast BaaS in C++. One binary, full backend, anywhere.</p><p><em>For the full changelog, see <a href="https://github.com/allankoechke/mantisbase/compare/v0.3.2...v0.3.3">v0.3.2...v0.3.3</a></em></p>]]></content:encoded></item><item><title><![CDATA[Smart Living & Leadership: Designing for Tomorrow]]></title><description><![CDATA[The second edition of the Smart Living & Tech Leadership Conference 2025 ran for two days, with intense, future-focused dialogue.]]></description><link>https://www.codeart.co.ke/p/smart-living-leadership-conf-2025</link><guid isPermaLink="false">https://www.codeart.co.ke/p/smart-living-leadership-conf-2025</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Thu, 13 Nov 2025 15:00:05 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3d86c76b-0cf0-4fdd-a220-7aa3349b4dbb_1080x625.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!D5rc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!D5rc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 424w, https://substackcdn.com/image/fetch/$s_!D5rc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 848w, https://substackcdn.com/image/fetch/$s_!D5rc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!D5rc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!D5rc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!D5rc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 424w, https://substackcdn.com/image/fetch/$s_!D5rc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 848w, https://substackcdn.com/image/fetch/$s_!D5rc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!D5rc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe84854ba-d768-4690-bcb7-ca758666597b_1080x625.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Smart Living &amp; Tech Leadership Conference Banner</figcaption></figure></div><p>The second edition of the <strong>Smart Living &amp; Tech Leadership Conference 2025</strong> ran for two days, with intense, future-focused dialogue. Day one set the foundation &#8212; sustainability, leadership, and the evolving role of cities in shaping human experience. Talks centred on energy management, mobility systems, and the ethics of digital transformation.</p><p>Day two shifted toward <strong>design, technology, and AI</strong>, unpacking how digital tools turn ideas into smarter, more liveable environments.</p><h3>The Core Idea</h3><p>Smart living isn&#8217;t about gadgets. It&#8217;s about intentional design. Every decision &#8212; spatial, structural, or digital &#8212; shapes how we live, move, and connect. Design is the link between people, data, and sustainability.</p><blockquote><p>&#128488;&#65039; "Design is not just what it looks like and feels like. Design is how it works."<br>&#8212; Steve Jobs</p></blockquote><p>Steve Jobs was a visionary who foretold of what it became of today, a fusion of design and functionality. A move toward designing for use rather than designing for aesthetics alone.</p><h3>My Session: Smart Living by Design</h3><p>I presented <strong>&#8220;Smart Living by Design: Evolving from Digital Tools to AI Decisions.&#8221; </strong>The session traced design&#8217;s evolution&#8212;from manual drafting to data-driven modelling and now to intelligent, AI-augmented systems.</p><ul><li><p>Digital tools like <strong>Revit</strong>, <strong>Inventor</strong>, <strong>3ds Max</strong>, and <strong>Maya</strong> redefined collaboration and precision.</p></li><li><p><strong>AI</strong> now extends creativity &#8212; generating forms, predicting outcomes, and guiding sustainable choices.</p></li><li><p>Projects like <strong>Bernini</strong> show how AI-driven 3D generation can reduce waste and optimise performance.</p></li><li><p><strong>Digital twins</strong> enable continuous feedback loops between the real and virtual worlds, making smart cities adaptive by design.</p></li></ul><p>The key takeaway: AI doesn&#8217;t replace creativity &#8212; it amplifies it. The future designer leads with intent, while AI accelerates exploration and insight.</p><h3>Conversations That Followed</h3><p>Post-session discussions were rich. People wanted to know how data models support interoperability across industries and where the limits of AI automation should be drawn. Others shared case studies on generative layouts for housing, mobility planning, and carbon analysis.</p><p>Outside the panels, the networking felt natural. Designers, engineers, urban planners, and educators connected over one shared vision &#8212; building systems that think with us, not for us.</p><h3>Closing Thought</h3><p>The conference reinforced a simple truth: <strong>design is leadership</strong>. Tools evolve, but human intention drives change. If we design with purpose &#8212; aligning creativity, technology, and sustainability &#8212; smart living becomes not an idea, but a lived reality.</p><p>Join the conversation!</p><div class="captioned-image-container"><figure><blockquote><p><a href="https://twitter.com/hashtag/Design?src=hash&amp;ref_src=twsrc%5Etfw">#Design</a> isn&#8217;t only about how it looks &#8212; it&#8217;s how it works.<br><br>At the Smart Living Conf, we explored how <a href="https://twitter.com/hashtag/AI?src=hash&amp;ref_src=twsrc%5Etfw">#AI</a> is becoming a design partner. From <a href="https://twitter.com/hashtag/AEC?src=hash&amp;ref_src=twsrc%5Etfw">#AEC</a> to <a href="https://twitter.com/hashtag/MFG?src=hash&amp;ref_src=twsrc%5Etfw">#MFG</a> and M&amp;E, AI helps us move ideas to reality; optimizing layouts, improving precision, and driving sustainable innovation. <a href="https://t.co/LO5NcE2wfk">pic.twitter.com/LO5NcE2wfk</a></p><p>&#8212; Allan K. Koech, HSC (@allankoechke) <a href="https://twitter.com/allankoechke/status/1986534803051839939?ref_src=twsrc%5Etfw">November 6, 2025</a></p></blockquote></figure></div>]]></content:encoded></item><item><title><![CDATA[Embedding Slint UI Within a Qt Application (C++)]]></title><description><![CDATA[Qt is a mature and feature-rich framework, but building flexible and declarative UIs often requires more than widgets and signals.]]></description><link>https://www.codeart.co.ke/p/embedding-slintui-within-qt-app</link><guid isPermaLink="false">https://www.codeart.co.ke/p/embedding-slintui-within-qt-app</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Fri, 10 Oct 2025 18:51:35 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fcbee22c-75c9-480a-a922-17b94b718d65_1920x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6Fuj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6Fuj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!6Fuj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!6Fuj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!6Fuj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6Fuj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6Fuj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!6Fuj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!6Fuj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!6Fuj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dc66be-94f2-4241-9eae-3f553cca4aad_1920x1080.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Embedding Slint UI in Qt Banner</figcaption></figure></div><p>Qt is a mature and feature-rich framework, but building flexible and declarative UIs often requires more than widgets and signals. That&#8217;s where Slint fits in. It provides a compact, declarative syntax for building modern UIs while staying native and lightweight.</p><p>Some Qt-based projects, like <em>LibrePCB</em>, already use Slint to modernise their UI without abandoning their existing Qt foundation. Check the full blog details <a href="https://librepcb.org/blog/2025-09-12_preview_of_next_gen_ui/">here</a>. Embedding Slint lets you:</p><ul><li><p>Keep your Qt app logic and backend code intact.</p></li><li><p>Use Slint for fast, declarative, and maintainable UI layers.</p></li><li><p>Mix and match Slint views with traditional Qt widgets.</p></li><li><p>Gradually migrate UI parts without a full rewrite.</p></li></ul><div><hr></div><p>Watch the walkthrough video here:</p><p>Slint UI 102: Embedding Slint UI Within a Qt Application | C++</p><div class="captioned-image-container"><figure><div id="youtube2-0ZPPeeCJA_k" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;0ZPPeeCJA_k&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/0ZPPeeCJA_k?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div></figure></div><div><hr></div><h2>What you&#8217;ll learn:</h2><ul><li><p>How to embed Slint UI components in a Qt app</p></li><li><p>How to compile <code>.slint</code> files to native C++</p></li><li><p>How to synchronise data between Qt and Slint</p></li><li><p>How to manage event flow and cleanup</p></li></ul><h2>Resources:</h2><ul><li><p>Slint Documentation: <a href="https://slint.dev/docs">https://slint.dev/docs</a></p></li><li><p>Slint Source Code: <a href="https://github.com/slint-ui/slint">https://github.com/slint-ui/slint</a></p></li><li><p>Slint C++ Template: <a href="https://github.com/slint-ui/slint-cpp-template">https://github.com/slint-ui/slint-cpp-template</a></p></li><li><p>Full Source Code from this video: <a href="https://github.com/allankoechke/qt-slint-integration-cpp">https://github.com/allankoechke/qt-slint-integration-cpp</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[[Youtube] What is Mantis?]]></title><description><![CDATA[We have earlier introduced Mantis, a C++ BaaS toolkit, designed to be lightweight but powerful.]]></description><link>https://www.codeart.co.ke/p/youtube-what-is-mantis</link><guid isPermaLink="false">https://www.codeart.co.ke/p/youtube-what-is-mantis</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Tue, 30 Sep 2025 22:50:28 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6be29692-7d84-4619-a95b-46710976b0e9_1920x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!t6Qf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!t6Qf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!t6Qf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!t6Qf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!t6Qf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!t6Qf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!t6Qf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!t6Qf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!t6Qf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!t6Qf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d99134f-8535-4e75-ba9c-29d02ed41ab1_1920x1080.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">What is Mantis?</figcaption></figure></div><p>We have earlier introduced Mantis, a C++ BaaS toolkit, designed to be lightweight but powerful.</p><blockquote><h4><a href="https://codeart.co.ke/introducing-mantis-the-lightweight-baas-in-cpp/">Introducing Mantis: The C++ Backend Framework Built for Simplicity and Speed</a></h4></blockquote><h1>What's changed?</h1><p>From our last v0.2.7 release a couple of weeks ago, we have some important fixes and improvements added to our v0.2.8 release. Have a look:</p><ul><li><p><em><strong>PostgreSQL Support</strong></em>: v0.2.8 brings full PostgreSQL support for Linux builds. This allows for easy backend database switch when scaling is required while maintaining lightweight backend database (SQLite) where it's needed. How do you switch the database? Easy!</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!A9jM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!A9jM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 424w, https://substackcdn.com/image/fetch/$s_!A9jM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 848w, https://substackcdn.com/image/fetch/$s_!A9jM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 1272w, https://substackcdn.com/image/fetch/$s_!A9jM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!A9jM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png" width="879" height="73" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:73,&quot;width&quot;:879,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!A9jM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 424w, https://substackcdn.com/image/fetch/$s_!A9jM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 848w, https://substackcdn.com/image/fetch/$s_!A9jM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 1272w, https://substackcdn.com/image/fetch/$s_!A9jM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cef2756-b0c2-47b9-bd2e-6e5b2c5c149d_879x73.png 1456w" sizes="100vw"></picture><div></div></div></a><figcaption class="image-caption">Connecting to PostgreSQL database</figcaption></figure></div><ul><li><p><em><strong>Minor bug fixes &amp; improvements</strong></em>: Lots of bugs were squashed, solving some performance issues as well as mending some issues that existed. Chief among these is matching data types compatibility for SQLite to/from PostgreSQL, forcing SQLite WAL mode checkpointing for every boot and refactoring project for performance improvements.</p></li></ul><div><hr></div><blockquote><h4><a href="https://github.com/allankoechke/mantis/releases/tag/v0.2.8">Release Release v0.2.8 &#183; allankoechke/mantis</a></h4></blockquote><div><hr></div><h1>Getting Started?</h1><p>We have a YouTube video to guide you out; don't fret. Checkout the video below for a walkthrough of the features mantis provides. If you have any question, lets discuss on YouTube or open a GitHub issue.</p><div class="captioned-image-container"><figure><div id="youtube2-5SdmabDqeqY" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;5SdmabDqeqY&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/5SdmabDqeqY?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div></figure></div><div><hr></div><p>Enjoy!</p>]]></content:encoded></item><item><title><![CDATA[Mantis v0.2.7-beta Release]]></title><description><![CDATA[We&#8217;ve shipped Mantis v0.2.7-beta, a new milestone for our lightweight pluggable backend-as-a-service (BaaS) framework written in C++.]]></description><link>https://www.codeart.co.ke/p/mantis-v0-2-7-beta-release</link><guid isPermaLink="false">https://www.codeart.co.ke/p/mantis-v0-2-7-beta-release</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Sat, 23 Aug 2025 19:20:15 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/62b794e9-a40e-4476-8417-ce777a485ad7_1500x752.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nf6E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nf6E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 424w, https://substackcdn.com/image/fetch/$s_!nf6E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 848w, https://substackcdn.com/image/fetch/$s_!nf6E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 1272w, https://substackcdn.com/image/fetch/$s_!nf6E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nf6E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nf6E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 424w, https://substackcdn.com/image/fetch/$s_!nf6E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 848w, https://substackcdn.com/image/fetch/$s_!nf6E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 1272w, https://substackcdn.com/image/fetch/$s_!nf6E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcbe2adf-076e-4cd4-ad9b-1fa4f757d175_1500x752.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Mantis v0.2.7 release banner</figcaption></figure></div><p>We&#8217;ve shipped <strong>Mantis v0.2.7-beta</strong>, a new milestone for our lightweight pluggable backend-as-a-service (BaaS) framework written in C++. This release focuses on making file management a first-class feature while continuing to strengthen stability and prepare for broader database support.</p><h2>Highlights</h2><h3>File and Files Field Support</h3><ul><li><p>Records now support <code>file</code> and <code>files</code> fields.</p></li><li><p>Upload, update, and remove files directly through record operations.</p></li><li><p>Safer filename handling with sanitization for long names and unknown characters.</p></li></ul><p>For more information on how to handle files in Mantis, check out the docs below:</p><blockquote><h4><a href="https://github.com/allankoechke/mantis/blob/master/doc/11.files.md">mantis/doc/11.files.md at master &#183; allankoechke/mantis</a></h4></blockquote><h3>Health check Endpoint</h3><ul><li><p>Added a <code>/api/v1/health</code> endpoint to make it easier to monitor and integrate Mantis into production setups.</p></li></ul><h3>Mantis Admin v0.1.7</h3><ul><li><p>Updated to the latest version of the Mantis Admin dashboard with file management capabilities.</p></li><li><p>Improved performance in the admin panel when working with larger datasets.</p></li></ul><h3>Bug Fixes and Improvements</h3><ul><li><p>Better handling of database value binding with <code>soci::values</code>.</p></li><li><p>Performance optimization for table ID generation.</p></li><li><p>More consistent cleanup of file references for updates and removals.</p></li></ul><h3>PostgreSQL Support (WIP)</h3><ul><li><p>Early integration of PostgreSQL via SOCI.</p></li><li><p>Initial support for builds, CLI commands, and CI/CD integration.</p></li><li><p>Still marked experimental but progressing quickly.</p></li></ul><blockquote><p>&#9888;&#65039; PostgreSQL support is experimental and currently only built for Linux. The feature still has unresolved issues and may fail to launch entirely.</p></blockquote><h2>Why It Matters</h2><p>Mantis is designed as an alternative to Firebase, Supabase, or PocketBase, but lighter, portable, and embeddable directly into your C++ applications. By keeping the runtime minimal and the architecture pluggable, we aim to make backend services faster to integrate and easier to run anywhere.</p><h2>What&#8217;s Next?</h2><ul><li><p>Complete PostgreSQL support for production use.</p></li><li><p>Expanded file access controls.</p></li><li><p>More integrations for different deployment targets.</p></li></ul><h2>Get Started</h2><p>GitHub Repo: <a href="https://github.com/allankoechke/mantis">https://github.com/allankoechke/mantis</a><br>Release Page: <a href="https://github.com/allankoechke/mantis/releases/tag/v0.2.7-beta">https://github.com/allankoechke/mantis/releases/tag/v0.2.7-beta</a><br>Documentation: <a href="https://docs.mantisapp.dev/">https://docs.mantisapp.dev/</a>.</p><div><hr></div><p>Feedback is welcome. If you try out the new file support or start testing PostgreSQL integration, please let us know how it works for you.</p>]]></content:encoded></item><item><title><![CDATA[Introducing Mantis: The C++ Backend Framework Built for Simplicity and Speed]]></title><description><![CDATA[In a world dominated by heavyweight frameworks and bloated deployment pipelines, Mantis stands out as a fast, modular C++ backend library designed for simplicity, speed, and embeddability.]]></description><link>https://www.codeart.co.ke/p/introducing-mantis-the-lightweight-baas-in-cpp</link><guid isPermaLink="false">https://www.codeart.co.ke/p/introducing-mantis-the-lightweight-baas-in-cpp</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Wed, 09 Jul 2025 21:11:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b30d0675-b9a3-44f9-b165-a92f462342a8_1187x594.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vmMv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vmMv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 424w, https://substackcdn.com/image/fetch/$s_!vmMv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 848w, https://substackcdn.com/image/fetch/$s_!vmMv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 1272w, https://substackcdn.com/image/fetch/$s_!vmMv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vmMv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vmMv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 424w, https://substackcdn.com/image/fetch/$s_!vmMv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 848w, https://substackcdn.com/image/fetch/$s_!vmMv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 1272w, https://substackcdn.com/image/fetch/$s_!vmMv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1edc2d4-dd7c-4cb0-93af-b8bd87b173c1_1187x594.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Introducing Mantis</figcaption></figure></div><p>In a world dominated by heavyweight frameworks and bloated deployment pipelines, <strong>Mantis</strong> stands out as a fast, modular C++ backend library designed for simplicity, speed, and embeddability. Whether you're building for the cloud, desktop, or embedded systems, Mantis gives you modern backend capabilities with zero friction.</p><h2>What Makes Mantis Special?</h2><h3>&#128640; Single Binary Deployment</h3><p>No containers, no dependencies, no problem. Mantis compiles to a single <code>mantisapp</code> binary that runs anywhere&#8212;just:</p><pre><code>./mantisapp serve -p 8000
</code></pre><p>It&#8217;s ideal for embedded devices, desktop applications, or servers where simplicity is paramount.</p><h3>Zero-Configuration REST APIs</h3><p>Define your tables&#8212;and that&#8217;s it. Mantis auto-generates RESTful CRUD endpoints, complete with JWT-based authentication and fine-grained access control.</p><h3>&#129504; Minimal Runtime Footprint</h3><p>With SQLite as the default database and tight memory usage, Mantis is engineered for environments where every byte counts.</p><div><hr></div><h2>Key Benefits That Set Mantis Apart</h2><h3>&#128295; Embeddable by Design</h3><p>Unlike traditional backends that require external deployment, Mantis can be embedded directly into your C++ application. Add backend functionality to Qt apps, CLI tools, or microservices&#8212;all from within your codebase.</p><h3>&#128272; Built-in Authentication &amp; Security</h3><p>Mantis handles token generation, validation, and route-level access control using JWT. You get secure, configurable auth out-of-the-box.</p><h3>&#128202; Lightweight Admin Dashboard</h3><p>Each Mantis deployment includes a built-in admin dashboard for managing tables, records, and users&#8212;no separate tooling or setup required.</p><h3>&#128051; Docker-Ready</h3><p>Mantis offers a Docker image with volume mounting support, ideal for containerized environments and CI/CD pipelines.</p><div><hr></div><h2>&#128736; Technology Stack</h2><p>Mantis integrates robust C++ libraries to deliver production-grade performance:</p><ul><li><p><strong>HTTP Server</strong>: <a href="https://github.com/yhirose/cpp-httplib"><code>httplib-cpp</code></a> for lightweight HTTP(S) handling</p></li><li><p><strong>Database</strong>: <a href="https://github.com/SOCI/soci"><code>SOCI</code></a> as an abstraction layer (SQLite by default; MySQL/PostgreSQL coming soon)</p></li><li><p><strong>Authentication</strong>: <a href="https://github.com/GlitchedPolygons/l8w8jwt"><code>l8w8jwt</code></a> for secure token management</p></li><li><p><strong>Logging</strong>: <a href="https://github.com/gabime/spdlog"><code>spdlog</code></a> for structured, high-performance logging</p></li></ul><div><hr></div><h2>&#128679; Future Vision: What&#8217;s Coming</h2><p>Mantis isn&#8217;t just stable&#8212;it&#8217;s growing. Here&#8217;s what&#8217;s on the horizon:</p><ul><li><p><strong>Real-Time Sync Engine</strong><br>WebSocket-powered data sync between clients and the backend&#8212;perfect for offline-first and collaborative apps.</p></li><li><p><strong>Full RDBMS Support</strong><br>Extend Mantis from SQLite to full support for MySQL and PostgreSQL with seamless migration tooling.</p></li><li><p><strong>Pluggable Middleware Architecture</strong><br>Customize request handling with user-defined middleware for logging, validation, authentication, or anything else.</p></li></ul><div><hr></div><h2>Getting Started is Effortless</h2><p>You can start using Mantis today in one of two ways:</p><h3>Option 1: Use Prebuilt Binaries</h3><p>Available for <strong>Linux (x86_64)</strong> and <strong>Windows (x64)&#8212;</strong><em>just download and run</em>.</p><h3>Option 2: Build From Source</h3><p>If you're targeting another platform or want to embed Mantis into your own C++ application:</p><pre><code>git clone --recurse-submodules https://github.com/allankoechke/mantis.git
cd mantis
cmake -B build
cmake --build build
./build/mantisapp serve -p 5000
</code></pre><p>Access the dashboard at <a href="http://localhost:5000/admin">http://localhost:5000/admin</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hPTi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hPTi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 424w, https://substackcdn.com/image/fetch/$s_!hPTi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 848w, https://substackcdn.com/image/fetch/$s_!hPTi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 1272w, https://substackcdn.com/image/fetch/$s_!hPTi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hPTi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png" width="2000" height="1085" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1085,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!hPTi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 424w, https://substackcdn.com/image/fetch/$s_!hPTi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 848w, https://substackcdn.com/image/fetch/$s_!hPTi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 1272w, https://substackcdn.com/image/fetch/$s_!hPTi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcd6579e-e4eb-471f-8eb8-269090d7dba9_3200x1736.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mantis Admin Dashboard (WIP)</figcaption></figure></div><p>&#128073; Read the full setup guide here:<br><strong><a href="https://allankoechke.github.io/mantis/setup.html">https://allankoechke.github.io/mantis/setup.html</a></strong></p><div><hr></div><h2>&#127775; Why Choose Mantis?</h2><p>In a space filled with over-engineered solutions, <strong>Mantis</strong> offers a refreshing alternative: modern backend functionality in a compact, embeddable C++ package. Whether you're targeting embedded devices, developer tools, or just want a backend that won&#8217;t get in your way&#8212;Mantis delivers.</p><div><hr></div><h3>Ready to Try It?</h3><p>Explore the <a href="https://github.com/allankoechke/mantis">GitHub repository</a>, download the binaries, and see what lightweight backend development really feels like.</p>]]></content:encoded></item><item><title><![CDATA[DeepWiki: How to Instantly Understand Any Codebase with AI-Powered Documentation]]></title><description><![CDATA[In the growing jungle of codebases, developer tools, and open-source libraries, one thing remains consistently frustrating: documentation.]]></description><link>https://www.codeart.co.ke/p/deepwiki-understand-any-codebase-with-ai</link><guid isPermaLink="false">https://www.codeart.co.ke/p/deepwiki-understand-any-codebase-with-ai</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Thu, 19 Jun 2025 15:00:47 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f5ffd3cf-9811-4bc5-8f2c-ba4172d55838_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-veB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-veB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!-veB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!-veB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!-veB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-veB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-veB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!-veB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!-veB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!-veB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7fde676-f6c8-4c01-a485-a23ef0c42a59_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Deepwiki: Chat with your codebase.</figcaption></figure></div><p>In the growing jungle of codebases, developer tools, and open-source libraries, one thing remains consistently frustrating: documentation. Whether they're too shallow, too outdated, or just missing altogether, bad docs slow everyone down. But what if you could talk to a codebase like you would a teammate? That&#8217;s where DeepWiki comes in.</p><blockquote><h4><a href="https://deepwiki.com/">DeepWiki | AI documentation you can talk to, for every repo</a></h4></blockquote><h3>What&#8217;s DeepWiki?</h3><p>It provides up-to-date documentation for any repo in the world that you can talk to. At first glance, you might consider it similar to your favorite LLM, but with the added context of a codebase.</p><blockquote><p>&#128161; A wiki is a form of hypertext publication on the internet which is collaboratively edited and managed by its audience directly through a web browser.&nbsp;A typical wiki contains multiple pages that can either be edited by the public or limited to use within an organization for maintaining its internal knowledge base.</p></blockquote><p>DeepWiki is powered by Devin AI, but over the past few months, there have been new open-source entrants to the space providing the same functionality.</p><h3>Where does it find its use?</h3><p>Consider this: the quality of documentation for repositories can range from excellent to inadequate. Imagine bumping into a repo with no docs, but it seems like a good fit for your needs. This scenario is where DeepWiki can help you create documentation for human understanding without needing to read through the entire codebase line by line.</p><p>You ask, it answers. From <em>"What does this function do?"</em> to <em>"How does authentication work in this repo?" </em>DeepWiki gives you direct, conversational insight based on the actual code, not assumptions.</p><p>It&#8217;s particularly useful when:</p><ul><li><p>You inherit a legacy code and need to quickly catch up.</p></li><li><p>You're actively participating in open-source projects and seeking to understand the internal workings.</p></li><li><p>You&#8217;re assessing a new library or tool and need to grasp its internals without reading 10 files.</p></li></ul><h3>But how does it work?</h3><p>Behind the scenes, DeepWiki syncs with the repository and builds an internal understanding of the code&#8212;structure, logic, and behavior. It doesn&#8217;t just summarize; it contextualizes. Ask a question, and it doesn&#8217;t respond based on generic training but refers to the actual code. That&#8217;s the difference.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!loHd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!loHd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 424w, https://substackcdn.com/image/fetch/$s_!loHd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 848w, https://substackcdn.com/image/fetch/$s_!loHd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 1272w, https://substackcdn.com/image/fetch/$s_!loHd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!loHd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png" width="200" height="103" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:103,&quot;width&quot;:200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!loHd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 424w, https://substackcdn.com/image/fetch/$s_!loHd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 848w, https://substackcdn.com/image/fetch/$s_!loHd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 1272w, https://substackcdn.com/image/fetch/$s_!loHd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fbffe42-3154-426a-b93f-0da605b37298_1516x787.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3>How do I get started?</h3><p>It's actually quite simple. On any GitHub repo you need to look into, replace the GitHub with the DeepWiki domain. For instance, for the SQLite repo above, replace <code>https://github.com/sqlite/sqlite</code> to <code>https://deepwiki.com/sqlite/sqlite</code>and there you'll be ready to chat with your repo.</p><blockquote><p>&#9888;&#65039; Note that not all repos are already indexed. For those that aren't, you'll have to request indexing and provide your email, and you'll be notified once indexing is completed. Usually in less than an hour or so.</p></blockquote><h3>Why it matters</h3><p>We&#8217;re entering a world where shipping fast isn't enough; you also need to <em>understand fast</em>. DeepWiki makes technical onboarding smoother, reduces context-switching, and adds clarity to chaos, especially in large or under-documented codebases.</p><p>Sure, it&#8217;s not a silver bullet. It won&#8217;t replace solid developer docs. But it&#8217;s a powerful fallback when the docs are missing, outdated, or nonexistent.</p><h3>Final thoughts</h3><p>In a way, DeepWiki brings back the original promise of AI in dev tooling&#8212;not to replace developers, but to augment them. It&#8217;s not just about code completion or chat-based assistance anymore; it&#8217;s about deep understanding. And in that space, DeepWiki has carved out something genuinely useful.</p><p>Whether you're delving deeply into a complex system or simply exploring a new library, DeepWiki is a valuable resource.</p><h3>FAQs</h3><blockquote><h4><strong>1. What is DeepWiki, and how does it work?</strong></h4><p>DeepWiki is an AI-powered tool by Devin AI that generates real-time, conversational documentation for any code repository. It analyzes the codebase and lets developers ask natural language questions to understand functionality, architecture, and workflows.</p></blockquote><blockquote><h4><strong>2. Can DeepWiki document private or internal repositories?</strong></h4><p>Yes, DeepWiki can be used with private repositories as long as you grant it access. It can then generate documentation and allow conversational querying based on your internal codebase.</p></blockquote><blockquote><h4><strong>3. How is DeepWiki different from ChatGPT or other AI coding assistants?</strong></h4><p>While general AI assistants like ChatGPT are trained on broad programming knowledge, DeepWiki is built to ingest and understand specific repositories, offering contextual, code-aware responses tailored to your exact codebase.</p></blockquote><blockquote><h4><strong>4. Is DeepWiki useful for teams and enterprise-level development?</strong></h4><p>Absolutely. DeepWiki can dramatically speed up developer onboarding, reduce time spent searching through code, and improve collaboration by acting as a living, interactive documentation layer for your projects.</p></blockquote><blockquote><h4><strong>5. Does DeepWiki replace traditional documentation?</strong></h4><p>No, but it complements it. While human-written documentation provides structure and intent, DeepWiki helps fill gaps, explain code in real time, and answer questions dynamically&#8212;especially when traditional docs are missing or outdated.</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Upgrading 3ds Max .NET Projects from .NET Framework to .NET 8]]></title><description><![CDATA[3ds Max 2025 and earlier versions have used the .NET Framework for building plugins, but, with the VFX world transitioning to .NET, 3ds Max 2026 brings this support with it. As such, .NET projects require a bit of housekeeping to get them compiled and wor]]></description><link>https://www.codeart.co.ke/p/upgrading-3dsmax-net-framework-projects-to-net8</link><guid isPermaLink="false">https://www.codeart.co.ke/p/upgrading-3dsmax-net-framework-projects-to-net8</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Sun, 01 Jun 2025 07:41:26 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/86aff209-0566-4c65-9b1e-46de0e6d95ca_2588x1292.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ftFi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ftFi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 424w, https://substackcdn.com/image/fetch/$s_!ftFi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 848w, https://substackcdn.com/image/fetch/$s_!ftFi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 1272w, https://substackcdn.com/image/fetch/$s_!ftFi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ftFi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ftFi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 424w, https://substackcdn.com/image/fetch/$s_!ftFi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 848w, https://substackcdn.com/image/fetch/$s_!ftFi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 1272w, https://substackcdn.com/image/fetch/$s_!ftFi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe89b88ae-ef63-4e72-a6d8-0e8d5a45b8f1_2588x1292.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">.NET Upgrade Assistant Installation</figcaption></figure></div><div><hr></div><p>Originally posted at:</p><blockquote><h4><a href="https://blog.autodesk.io/upgrading-3ds-max-net-projects-from-net-framework-to-net-8/">Autodesk Developer BlogUpgrading 3ds Max .NET projects from .NET Framework to .NET 8</a></h4></blockquote><div><hr></div><p>3ds Max 2025 and earlier versions have used the .NET Framework for building plugins, but, with the VFX world transitioning to .NET, 3ds Max 2026 brings this support with it. As such, .NET projects require a bit of housekeeping to get them compiled and working in .NET 8 for our case. This blog is a simple walkthrough of the upgrade process, using the public <em><strong>Explode Geometry</strong></em> Sample hosted <a href="https://github.com/ADN-DevTech/3dsMax-Explode-Geometry">here</a>.</p><h2><strong>The Upgrade Assistant</strong></h2><p>Microsoft provides an <em><a href="https://dotnet.microsoft.com/en-us/platform/upgrade-assistant">Upgrade Assistant</a></em> extension to help with porting .NET Framework projects to .NET as well as .NET Core to .NET and much more. The tool simplifies and aids in handling the upgrade intricacies, leaving just a few more steps for us to complete.</p><p>First, to get things going, check if you have the Upgrade Assistant installed. If not installed, the <em><strong>Visual Studio Extensions Manager</strong></em><strong> </strong>should be your first stop. With Visual Studio opened, navigate to <em>Menu &gt; Extensions &gt; Manage Extensions. </em>Under the Extensions Manager, search for <em>Upgrade Assistant</em> and get it installed as shown below.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FHCl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FHCl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 424w, https://substackcdn.com/image/fetch/$s_!FHCl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 848w, https://substackcdn.com/image/fetch/$s_!FHCl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 1272w, https://substackcdn.com/image/fetch/$s_!FHCl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FHCl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png" width="800" height="399" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:399,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!FHCl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 424w, https://substackcdn.com/image/fetch/$s_!FHCl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 848w, https://substackcdn.com/image/fetch/$s_!FHCl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 1272w, https://substackcdn.com/image/fetch/$s_!FHCl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84bfb8f3-db7d-4750-b197-f9b711174d37_800x399.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Install Upgrade Asistant</figcaption></figure></div><p>With the assistant downloaded, follow the instructions to get it installed. This may include having to restart the IDE to get the extension installed and loaded for use.</p><blockquote><p>Please note that the Upgrade Assistant is available as both a Visual Studio extension and a command-line utility. In this blog, we will only cover using the Visual Studio extension.</p></blockquote><h2>Explode Geometry Project .NET Upgrade</h2><p>Let's work with our [ADN Explode Geometry Sample] (GitHub link) available on GitHub and see how we can get it building and running in .NET 8.</p><h3>Fetching the project</h3><p>This is an easy step: clone the repo <em>(SSH, HTTPS, ZIP, or any format you prefer)</em>. Note that our GitHub repo is already updated, so fetch the older tagged version for the 2025 code for the sample.</p><pre><code>git clone --branch v2.7 https://github.com/ADN-DevTech/3dsMax-Explode-Geometry
cd 3dsMax-Explode-Geometry</code></pre><p>In the Source folder, open the .csproj in Visual Studio.</p><h3>Upgrading to .NET the Assistant way</h3><p>As detailed in the Microsoft blog on the assistant, we can upgrade by right-clicking the project and selecting Upgrade. This opens a new project upgrade page.</p><p>Here, we select the project upgrade way and work with the <em><strong>in-place project upgrade,</strong></em> but feel free to test the other options if they suit your needs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3W_C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3W_C!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 424w, https://substackcdn.com/image/fetch/$s_!3W_C!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 848w, https://substackcdn.com/image/fetch/$s_!3W_C!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 1272w, https://substackcdn.com/image/fetch/$s_!3W_C!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3W_C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png" width="800" height="337" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3de06d9-f8e3-451e-976f-91e501185774_800x337.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:337,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!3W_C!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 424w, https://substackcdn.com/image/fetch/$s_!3W_C!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 848w, https://substackcdn.com/image/fetch/$s_!3W_C!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 1272w, https://substackcdn.com/image/fetch/$s_!3W_C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3de06d9-f8e3-451e-976f-91e501185774_800x337.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Selecting the .NET version</figcaption></figure></div><p>With the <em>upgrade type</em> ironed out, next, we need to select the <em>.NET version</em> to upgrade to. For our case, we are going for <em><strong>.NET 8.0 LTS;</strong></em> this is the expectation for 3ds Max 2026 .NET plugins. You may optionally get an action requirement to download and install <em>.NET SDK</em> if you don't have it yet; if so, proceed with that installation, then pick it up from here once done.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-d-a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-d-a!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 424w, https://substackcdn.com/image/fetch/$s_!-d-a!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 848w, https://substackcdn.com/image/fetch/$s_!-d-a!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 1272w, https://substackcdn.com/image/fetch/$s_!-d-a!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-d-a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png" width="800" height="349" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5bcce68-9284-4534-86c2-996031715841_800x349.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:349,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!-d-a!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 424w, https://substackcdn.com/image/fetch/$s_!-d-a!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 848w, https://substackcdn.com/image/fetch/$s_!-d-a!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 1272w, https://substackcdn.com/image/fetch/$s_!-d-a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5bcce68-9284-4534-86c2-996031715841_800x349.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">.NET version</figcaption></figure></div><p>In the next step, we are required to select the files to upgrade. By default, all files in the project are checked, including the project file. Let's leave it as is and proceed with upgrading the selection. After the process completes, if no errors come up, then our project will have been transformed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!02Rd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!02Rd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 424w, https://substackcdn.com/image/fetch/$s_!02Rd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 848w, https://substackcdn.com/image/fetch/$s_!02Rd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 1272w, https://substackcdn.com/image/fetch/$s_!02Rd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!02Rd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png" width="1565" height="825" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:825,&quot;width&quot;:1565,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Upgrade completion status. Some warnings for now, nothing to worry about.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Upgrade completion status. Some warnings for now, nothing to worry about." title="Upgrade completion status. Some warnings for now, nothing to worry about." srcset="https://substackcdn.com/image/fetch/$s_!02Rd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 424w, https://substackcdn.com/image/fetch/$s_!02Rd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 848w, https://substackcdn.com/image/fetch/$s_!02Rd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 1272w, https://substackcdn.com/image/fetch/$s_!02Rd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc029e1-d5de-4e5a-a373-420b00e0ec53_1565x825.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Upgrade completion status. Some warnings for now, nothing to worry about.</figcaption></figure></div><p>Probably, the project will try to build but fail; we will fix that shortly. To check the logs, switch the combo box as shown below to the Upgrade Assistant option.</p><p>At the end of this process, you should have a project file <code>`.csproj`</code> that has been updated to conform to the .NET 8 project format. Running the build fails due to missing references to the Autodesk assemblies that may have been dropped in the upgrade process. Don't worry; fixing this is easy!</p><p>To fix the missing Autodesk assemblies or any other internal or 3rd party assemblies, we can achieve that either by;</p><ul><li><p>Directly edit the <code>csproj</code> file by copying the <em>ItemGroup</em> for the assemblies from the old project file and updating where necessary. For instance, for the Autodesk.Max.dll assembly, we can have it included in the new project file as shown below, with the version updated to 2026, of course. The same will be done for the other project dependencies like <code>CSharpUtilities.dll, ManagedServices.dll</code>, etc.</p></li></ul><pre><code>&lt;ItemGroup&gt;
  &lt;Reference Include="Autodesk.Max"&gt;
    &lt;HintPath&gt;$(ADSK_3DSMAX_x64_2026)\Autodesk.Max.dll&lt;/HintPath&gt;
    &lt;Private&gt;False&lt;/Private&gt;
  &lt;/Reference&gt; .... other assemblies
&lt;/ItemGroup&gt;</code></pre><ul><li><p>Another way is making use of the Visual Studio Reference Manager that is accessed from the <strong><code>Menu &gt; Project &gt; Add Project Reference &gt; Browse</code></strong> &amp; find your assemblies. Once all intended libraries are selected, click OK to add them. Just as in the option above, the new assemblies will be added back into the project file. Just FYI, we can change the assembly paths for the Autodesk assemblies to make use of the path variables. This way, any user can use our plugin despite the installation path they chose. For our case, we will use the path as<em><strong> $(ADSK_3DSMAX_x64_2026)\&lt;assembly name&gt;</strong></em>.&nbsp;</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AVAY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AVAY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 424w, https://substackcdn.com/image/fetch/$s_!AVAY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 848w, https://substackcdn.com/image/fetch/$s_!AVAY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 1272w, https://substackcdn.com/image/fetch/$s_!AVAY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AVAY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png" width="800" height="399" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ebe83595-e3f3-4e80-a070-a76ba584b143_800x399.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:399,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!AVAY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 424w, https://substackcdn.com/image/fetch/$s_!AVAY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 848w, https://substackcdn.com/image/fetch/$s_!AVAY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 1272w, https://substackcdn.com/image/fetch/$s_!AVAY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febe83595-e3f3-4e80-a070-a76ba584b143_800x399.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Add ASM reference.</figcaption></figure></div><p>At this stage, we can build our project, and everything should now be okay. But, looking at the logs, our build outputs are going to the default Visual Studio project build directory and not the one defined under our <em><strong>debug/release</strong></em> property group. In .NET Framework project configuration, we had defined <em><strong>&lt;OutputPath&gt;</strong></em> inside each build type (Build/Debug); in .NET, we define it inside the first global <em>&lt;PropertyGroup&gt;</em> where we have our project defaults, as shown below:</p><pre><code>&lt;PropertyGroup&gt;
  &lt;TargetFramework&gt;net8.0-windows&lt;/TargetFramework&gt;&nbsp;&nbsp;
  ... the other config here
  &lt;OutputPath&gt;C:\Our\intended\path\for\the\assembly&lt;/OutputPath&gt;&nbsp;
&lt;/PropertyGroup&gt;</code></pre><p>For our case, we will be using the Autodesk plugin path as our output path. This way, any plugin development changes can be updated in the plugin directory for testing.</p><p>Note: There may be extra steps to getting the assembly loaded into 3ds Max. If using <em><strong>PackageContents.xml</strong></em>, update where necessary to get the assembly and its dependencies loaded. Refer to the following documentation pages for help: <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=menu_migration_guide">Menu System Migration</a>, <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=packaging_plugins">Packaging Samples</a>&nbsp;</p><h3>Final Housekeeping&nbsp;</h3><p>As a close, we need to do a bit of housekeeping. Here are a few things to consider:</p><ul><li><p>Setting included assemblies as not private: When we add assembly references in our project, the build process ends up copying the assembly references and their dependencies to the `OutputPath` directory, which is not the intended behavior. This results in duplication of assemblies, which may cause 3ds Max to crash. To resolve this, update each of the included assemblies as follows:</p></li></ul><pre><code>&lt;Reference Include="ManagedServices"&gt;&nbsp;
  &lt;HintPath&gt; $(ADSK_3DSMAX_x64_2026)\ManagedServices.dll &lt;/HintPath&gt;&nbsp;&nbsp;
  &lt;Private&gt; false &lt;/Private&gt;&nbsp;
&lt;/Reference&gt;&nbsp;</code></pre><ul><li><p>Disabling <code>AppendTargetFrameworkToOutputPath</code>&nbsp;flag: Since plugins for 3ds Max are meant for Windows, we can disable the flag above to ensure the assemblies don't end up nested in a target framework directory.</p></li></ul><pre><code>&lt;AppendTargetFrameworkToOutputPath&gt; false &lt;/AppendTargetFrameworkToOutputPath&gt;</code></pre><ul><li><p>Updating/bumping up plugin versions. This applies to both ApplicationVersion and AssemblyVersion</p></li><li><p>Cleaning up some left-behind <code>&lt;ItemGroup&gt;</code> locks, which are not required in .NET 8.</p></li><li><p>Since our plugin is intended to run only on the Windows platform, expect to see lots of <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/code-analysis/5.0/ca1416-platform-compatibility-analyzer">warnings on platform compatibility</a>. We can safely ignore these warnings using the snippet below:</p></li></ul><pre><code>&lt;NoWarn&gt;$(NoWarn);CA1416&lt;/NoWarn&gt;</code></pre><p>You can find the complete upgraded sample on our <a href="https://github.com/ADN-DevTech/3dsMax-Explode-Geometry/tree/v2.8">ADN GitHub repo</a> for reference.</p><div><hr></div><p>What did I miss out on? Please let us know! Happy upgrading: smile:!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ujtT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ujtT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 424w, https://substackcdn.com/image/fetch/$s_!ujtT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 848w, https://substackcdn.com/image/fetch/$s_!ujtT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 1272w, https://substackcdn.com/image/fetch/$s_!ujtT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ujtT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png" width="2000" height="1220" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1220,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!ujtT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 424w, https://substackcdn.com/image/fetch/$s_!ujtT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 848w, https://substackcdn.com/image/fetch/$s_!ujtT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 1272w, https://substackcdn.com/image/fetch/$s_!ujtT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85892715-d98d-4c78-86a6-6ddfbf2dc43c_2736x1669.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Side by side (triangle vs polygon) explode geometry results.</figcaption></figure></div>]]></content:encoded></item><item><title><![CDATA[What's new in 3ds Max 2026?]]></title><description><![CDATA[A few weeks ago, 3ds Max 2026 saw its official release, introducing new features and capabilities for both artists and developers.]]></description><link>https://www.codeart.co.ke/p/whats-new-in-3ds-max-2026</link><guid isPermaLink="false">https://www.codeart.co.ke/p/whats-new-in-3ds-max-2026</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Fri, 30 May 2025 21:00:27 GMT</pubDate><enclosure url="https://codeart.co.ke/content/images/2025/05/image001.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://codeart.co.ke/content/images/2025/05/image001.jpg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://codeart.co.ke/content/images/2025/05/image001.jpg 424w, https://codeart.co.ke/content/images/2025/05/image001.jpg 848w, https://codeart.co.ke/content/images/2025/05/image001.jpg 1272w, https://codeart.co.ke/content/images/2025/05/image001.jpg 1456w" sizes="100vw"><img src="https://codeart.co.ke/content/images/2025/05/image001.jpg" data-attrs="{&quot;src&quot;:&quot;https://codeart.co.ke/content/images/2025/05/image001.jpg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://codeart.co.ke/content/images/2025/05/image001.jpg 424w, https://codeart.co.ke/content/images/2025/05/image001.jpg 848w, https://codeart.co.ke/content/images/2025/05/image001.jpg 1272w, https://codeart.co.ke/content/images/2025/05/image001.jpg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Image courtesy of Mohanad Hossam</figcaption></figure></div><p>A few weeks ago, 3ds Max 2026 saw its official release, introducing new features and capabilities for both artists and developers. With this release, 3ds Max saw many upgrades in <em>Arnold to 5.8</em>, <em>Substance to 3.0.8</em>, <em>performance improvements</em> in different modifiers, and much more. Refer to the <a href="https://help.autodesk.com/view/MAXDEV/2026/ENU/?guid=whats_new_3dsmax_2026_sdk">release page</a> for a detailed feature change for 3ds Max 2026.</p><div><hr></div><p>Originally Posted At:</p><blockquote><h4><a href="https://blog.autodesk.io/whats-new-in-3ds-max-2026/">Autodesk Developer BlogWhat&#8217;s new in 3ds Max 2026?</a></h4></blockquote><div><hr></div><h2>SDK Changes</h2><p>First, let's discuss the SDK changes that came with 3ds Max 2025 last year. We didn't have full information then, as there were breaking changes that are now fully documented.</p><ul><li><p>&nbsp;3ds Max 2025 came with a revamped new menu system. The update necessitates the rewriting of all plugins that generate menus or quad menus to align with 3ds Max 2025. Check out more information on the <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=GUID-FF48D0EC-6669-4EC7-AB43-E9998A14A198">menu changes</a>, <a href="https://help.autodesk.com/view/MAXDEV/2026/ENU/?guid=menu_migration_guide">menu migration guide</a>, and <a href="https://codeart.co.ke/porting-plugins-from-3ds-max-2024-to-3ds-max-2025/">general plugin migration guide to 2025 using the Explode Geometry Sample</a>.</p></li></ul><p>With that out of the way, what's new in 2026?</p><ul><li><p>NET 8.0 Support: In 2026, .NET 8 support for plugin development was introduced to align with Autodesk's goal of updating all our projects to more modern standards. This upgrade is a shift from the framework-based projects of previous 3ds Max versions; as such, this breaking change will require project restructuring and rebuilding to work in 2026. Refer to our <a href="https://codeart.co.ke/upgrading-3dsmax-net-framework-projects-to-net8/">porting guide from .NET Framework to .NET for plugins</a>.</p></li><li><p>Lots of minor API changes in ActionTable, Animatable, CustCont, ColorManagement, Menu System, etc. for performance and/or added functionality.</p></li><li><p>SDK licensing updates: SDK header licenses have been updated for conformity to the Autodesk license agreement, which is provided at the time of installation or download.</p></li><li><p>Updated samples and documentation to reflect API changes.</p></li></ul><p>Refer to our <a href="https://help.autodesk.com/view/MAXDEV/2026/ENU/?guid=whats_new_3dsmax_2026_sdk">What's New</a> docs section for a full list of API &amp; SDK changes in 2026.</p>]]></content:encoded></item><item><title><![CDATA[Porting Plugins from 3ds Max 2024 to 3ds Max 2025]]></title><description><![CDATA[3ds Max 2025 came with some breaking changes that marked an era of new approaches aimed at improving performance at the core.]]></description><link>https://www.codeart.co.ke/p/porting-plugins-from-3ds-max-2024-to-3ds-max-2025</link><guid isPermaLink="false">https://www.codeart.co.ke/p/porting-plugins-from-3ds-max-2024-to-3ds-max-2025</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Fri, 30 May 2025 06:54:49 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b252223d-dbed-4982-ab84-730ea45fe816_1040x450.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9IkT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9IkT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9IkT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9IkT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9IkT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9IkT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9IkT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9IkT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9IkT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9IkT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d90aae3-8f6f-4595-874c-4d3049034934_1040x450.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Image courtesy of Autodesk 3ds Max Announcement</figcaption></figure></div><p>3ds Max 2025 came with some breaking changes that marked an era of new approaches aimed at improving performance at the core. As a result, some tools tailored to pre-2025 3ds Max versions may fail to load into 2025. In this blog, we will give you a walkthrough of how to handle porting a plugin to 2025, using one of our samples as a base example.</p><div><hr></div><p>Originally Posted:</p><blockquote><h4><a href="https://blog.autodesk.io/porting-plugins-from-3ds-max-2024-to-3ds-max-2025/">Autodesk Developer BlogPorting Plugins from 3ds Max 2024 to 3ds Max 2025</a></h4></blockquote><div><hr></div><h2>What Changed in 2025?</h2><p>2025 brings some exciting changes; here are some highlights:</p><ul><li><p><em><strong>Menu Changes</strong></em>: 3ds Max 2025 introduces an overhaul of the menu system, deprecating the old <code>MenuManager (menuMan)</code> and introducing the new CuiMenuManager and its associated classes. This brings more ways of creating menus, statically or dynamically.</p></li><li><p><em><strong>shape.h</strong></em>: Introduced 8 helper methods for enhanced Bezier shape handling and end cap material options to improve shape rendering and control.</p></li><li><p><em><strong>spline3d.h</strong></em>: Added methods for checking spline segment linearity , managing angle constraints, and enhancing spline manipulation capabilities.</p></li><li><p><em><strong>splshape.h</strong></em>: Implemented methods to override spline closure prompts, providing customizable control over user interface prompts.</p></li><li><p><em><strong>mnmesh.h</strong></em>: Introduced new classes and optimizations for vertex origins and mesh management, focusing on performance improvements with complex meshes.</p></li><li><p><em><strong>Mesh.h</strong></em>: We have added a helper method in <em>ScopedLockChannels</em> to efficiently update transformed bounding boxes, thereby enhancing mesh rendering accuracy.</p></li><li><p><em><strong>MaxGuid.h</strong></em>: Introduced the MaxGuid class for GUID management within MaxSDK, facilitating efficient unique identifier handling.</p></li><li><p><em><strong>iparamm2.h</strong></em>: A virtual SetRange method has been added for defining UI control ranges, enabling flexible parameter range customization.</p></li><li><p><em><strong>imorpher.h</strong></em>: Established interface classes for Morpher modifiers, expanding morphing capabilities with multiple channels of geometric transformation control.</p></li><li><p><em><strong>control.h</strong></em>: Implemented the GetDefaultController method to select appropriate user controls based on parameter types, ensuring efficient and accurate UI element assignment.</p></li></ul><p>Now that you have seen some SDK changes in 2025, let's see how you would <em>port a 2024 sample to work with 3ds Max 2025</em>.</p><h2>Porting the Explode Geometry Sample</h2><p>The Explode Geometry Sample is one of the sample plugins maintained by the <a href="https://aps.autodesk.com/adn">ADN team</a>, with the installer available on the <a href="https://apps.autodesk.com/3DSMAX/en/Detail/Index?id=2091841125298582567&amp;appLang=en&amp;os=Win64">Autodesk App Store</a> and the source code hosted on the <a href="https://github.com/ADN-DevTech">ADN GitHub repo</a>. To begin the porting process, let's begin with fetching the code we will be working with.</p><h3>Fetching the source code</h3><p>Using your favourite tool, whether<em> GitHub Desktop, SourceTree, the command line</em>, etc., clone the Explode Geometry Sample. Note that you need to clone on the version tag indicated below, as the code has been updated already to support newer versions of 3ds Max.</p><pre><code>// Lets fetch code from v2.6 tag which supports 3ds Max 2024
// https://github.com/ADN-DevTech/3dsMax-Explode-Geometry/releases/tag/v2.6
git clone --branch v2.6 https://github.com/ADN-DevTech/3dsMax-Explode-Geometry.git
cd 3dsMax-Explode-Geometry
</code></pre><h3>Updating to 2025 Assembly Versions</h3><p>First, let's start by updating the assembly reference version to 3ds Max 2025 as well as setting our assembly output directory to 2025. In the <em><strong>.csproj</strong></em> project file, update the occurrence of 2024 to 2025, the assumption here being that you already have the 3ds Max 2025 setup installed.</p><p>With the project version updated, another interesting section to update is in our <em><code>AssemblyInfo.cs</code></em> file. Here we have predefined assembly versions and other organizational details, which may need to be bumped up to match the 3ds Max 2025 version.</p><pre><code>// Update the following two lines if need be
[assembly: AssemblyVersion("2.7.0.0")]
[assembly: AssemblyFileVersion("2.7.0.0")]</code></pre><p>At this point, we have all versioning details updated and ready to work on 2025 feature changes. First, let's look at our core functionality.</p><blockquote><p>Note: The system requirements for .NET are v4.8, if you have any build issues with version incompatibility, switch to v4.8.1.</p></blockquote><h3>MNVert Changes</h3><p>As noted earlier about some small changes to the C++ API that affect .NET-generated code, MNVert is among the victims of performance optimization. With the C++ API dropping the original copy operator for the C++ default copy, making MNVert trivially copiable and allocatable. This subtle change that works the same on the C++ side results in missing the `<em>Assign</em>` operator on the .NET `MNVert`.</p><p>Below is the final output for the 2024 vs. 2025 `<em>ExplodeGeometry</em>` with the MNVert functionality unchanged. You will note that the 2025 version shows no shapes on the scene as the Assign method is missing, which assigns vertex points to the `<em>polyNewFace</em>` which we are using to create new faces.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9U9M!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9U9M!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 424w, https://substackcdn.com/image/fetch/$s_!9U9M!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 848w, https://substackcdn.com/image/fetch/$s_!9U9M!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 1272w, https://substackcdn.com/image/fetch/$s_!9U9M!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9U9M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png" width="800" height="253" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:253,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!9U9M!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 424w, https://substackcdn.com/image/fetch/$s_!9U9M!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 848w, https://substackcdn.com/image/fetch/$s_!9U9M!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 1272w, https://substackcdn.com/image/fetch/$s_!9U9M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cbec2c7-0019-46a9-a337-171f434a6aee_800x253.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Visual changes in 3ds Max 2024 and 3ds Max 2025</figcaption></figure></div><p>&nbsp;How can we remedy this? A quick fix is as shown below:</p><pre><code>// Original code ..
polyNewFace.Mesh.V(k).Assign(vert);
// New code ...
polyNewFace.Mesh.V(k).P = vert.P;</code></pre><blockquote><p>Note that the method `<em><strong>Assign</strong></em>` still works on the `<em>MNVert</em>`, but this originates from the `FlagUser`, where `MNVert` derives from.</p></blockquote><p>With that fixed, let's have a look at the menu system changes and how to effect those changes in our sample.</p><h3>Upgrading to the new Menu System</h3><p>Unfortunately, we will go over all the menu changes and how to make use of them here, but you can find a detailed guide on the following topic below:</p><ul><li><p>The Menu System: <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=GUID-FF48D0EC-6669-4EC7-AB43-E9998A14A198">https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=GUID-FF48D0EC-6669-4EC7-AB43-E9998A14A198</a> &amp; <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=menu_system">https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=menu_system</a></p></li><li><p>Menu Migration Guide: <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=menu_migration_guide">https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=menu_migration_guide</a></p></li></ul><p>&nbsp;The sample packs a few useful packaging scripts and configuration files. This is where we will be modifying to set up the menu changes. But first, why do we need to make use of the menu in this sample?</p><p>The sample is distributed as part of the ADN samples through the Autodesk AppStore. As such, to invoke the sample:</p><ul><li><p><em>First, the assembly must be loaded to 3ds Max, which we are achieving by using the `PackageContents.xml` file. You can check the section on ` Packaging Your Project` in the Menu Migration Guide linked above.</em></p></li><li><p><em>Secondly, we expose the action items through MacroScript. This is not necessary, as we can make use of the Action table IDs directly to invoke the .NET methods.</em></p></li><li><p><em>Lastly, we create a menu entry under the `<code>App Store</code>` menu item on the main menu bar.</em></p></li></ul><p>With all that in mind, let's navigate to the `<em><code>PackageContents.xml</code></em>` located in the `<em><code>/Bundle2</code></em>` directory and start the packaging process upgrade.</p><h3>PackageContents.xml file</h3><p>First, let's expand the package runtime environment to support 2025. This can be done by updating the `<em><code>SeriesMax</code></em>` value to 2025. Similarly, let's expand the `<em><code>SeriesMax</code></em>` for `<em><code>macroscripts parts</code></em>` segment as shown below:</p><pre><code>&lt;RuntimeRequirements
&nbsp;&nbsp;&nbsp;&nbsp;OS="Win64"
&nbsp;&nbsp;&nbsp;&nbsp;Platform="3ds Max"
&nbsp;&nbsp;&nbsp;&nbsp;SeriesMin="2020"
&nbsp;&nbsp;&nbsp;&nbsp;SeriesMax="2025"
/&gt;
&lt;Components Description="macroscripts parts"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;RuntimeRequirements ... SeriesMax="2025" /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;...
&lt;/Components&gt;</code></pre><p>With MacroScript support for 2025 added, let's add .NET assembly as shown below.</p><pre><code>&lt;Components Description="assemblies parts"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;RuntimeRequirements OS="Win64" Platform="3ds Max" SeriesMin="2025" SeriesMax="2025" /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ComponentEntry AppName="ADNExplodeGeometry" Version="2.6.0" ModuleName="./Contents/ManagedAssemblies/2025/ADNExplodeGeometry.dll" AppDescription="..." /&gt;
&lt;/Components&gt;</code></pre><p>Lastly, let's add a post-startup script for 2025 that will create the menu entry for us on 3ds Max boot. Don't worry for now; we'll create the actual file and its contents next.</p><pre><code>&lt;Components Description="post-start-up scripts parts"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;RuntimeRequirements OS="Win64" Platform="3ds Max" SeriesMin="2025" SeriesMax="2025" /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ComponentEntry AppName="ADNExplodeGeometry" Version="2.6.0" ModuleName="./Contents/Post-Start-Up_Scripts/ADNGeometryExplodeSetupMenu2025.ms" AppDescription="Setup Menu to execute tool" /&gt;
&lt;/Components&gt;</code></pre><h3>&nbsp;Creating Menu Entries for 2025</h3><p>As we noted above in the `PackageContents.xml`, we need to add a new post-startup script that will handle menu creation for our package when it's loaded. We create a new file called ` <em>ADNGeometryExplodeSetupMenu2025.ms</em>` in the <em>`./Bundle2/Contents/Post-Start-Up_Scripts/</em>` directory. Unlike 3ds Max 2024 and earlier versions, 2025 uses callbacks to register new menu entries for both regular and quad menus.</p><p>Within the file, let's add code to register our callback as well as get the main menu bar handle, which we will use to add new menu or submenu entries.</p><pre><code>function menuCallback = (
&nbsp;&nbsp;&nbsp;&nbsp;local menuMgr = callbacks.notificationParam()
&nbsp;&nbsp;&nbsp;&nbsp;local mainMenuBar = menuMgr.mainMenuBar
)

-- Register Callback to the #CuiRegisterMenus
callbacks.removeScripts id:#adnExplodeGeomMenu
callbacks.addScript #cuiRegisterMenus menuCallback id:#adnExplodeGeomMenu</code></pre><p>From the callback, we can access the menu manager, which hosts the main menu bar. We'll use the main menu bar to add a sub-menu item, which will have our menu item. Let's see how this is attained:</p><pre><code>local stringAppStoreDefaultMenu = "App Store"
-- ADN Explode Geometry MXS
local stringMacroScriptName = "ADNExplodeGeomMS"
local stringMacroScriptCategory = "ADN Samples"
local helpMenuId = "cee8f758-2199-411b-81e7-d3ff4a80d143"

-- ID of the "App Store" menu in the menu bar. Use this ID when in need of adding new submenu items to the "App Store" menu entry.
local appStoreMenuId = "CC18FEFC-E8A4-4B16-B519-664E8FA3B549"
local newSubMenu = mainMenuBar.CreateSubMenu appStoreMenuId stringAppStoreDefaultMenu beforeId:helpMenuId

local separatorId = "96FB49D4-6263-4D8E-AC95-6D304673327B"
newSubMenu.CreateSeparator separatorId
local permanentId = stringMacroScriptName + "`" + stringMacroScriptCategory

-- 647394: MacroScript Action Table ID
newSubMenu.CreateAction "9DE5BDB9-E47F-4614-BDF8-C331B9B38C70" 647394 permanentId</code></pre><p>This script defines some local variables like the menu entry name and our menu name, as well as some system data like the `<em><strong>Help Menu</strong></em>` GUID. From the main menu bar, we create a submenu called `App Store` using <em><code>mainMenuBar.CreateSubMenu&#8291;. </code></em>In the submenu, we add a separator at the end of the existing menu items, if any (in our case it may be empty), and then we create a new action entry for our sample.</p><p>With the script completed, we have one last piece remaining: adding the built assembly to the package.</p><h3>Building &amp; Adding Assembly to the Package</h3><p>Under the `<em><code>PackageContents.xml</code></em>` section, we added a reference to a built assembly supporting 2025. From our upgraded project, we build our project, and the generated assembly is written out to our project's <em>`OutputPath</em>` directive. We can copy over this assembly to the <em>`<code>./Bundle2/Contents/ManagedAssemblies/2025/</code>`</em> directory.</p><p>The Bundle2 directory can be copied over as is now to the 3ds Max plugin directory, and on the next 3ds Max boot, the plugin will be loaded. For a full guide to plugin packaging, check the docs here: <a href="https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=packaging_plugins">https://help.autodesk.com/view/MAXDEV/2025/ENU/?guid=packaging_plugins</a>.</p><h2>Final touches</h2><p>To finalise the plugin details, we can do a couple of things:</p><ul><li><p>&nbsp;Update version information for the plugin, as encompassed in the `<em><code>PackageContents.xml</code></em>`</p></li><li><p><em>Documentation</em>: Updating the documentation details for new features, fixes, and/or new version information.</p></li></ul><p>We hope you found that helpful!</p>]]></content:encoded></item><item><title><![CDATA[Slint 101: The Basics]]></title><description><![CDATA[What is Slint? Slint is a cross-platform UI toolkit written in Rust with language bindings for C++, JavaScript, Python, and much more. As a cross-platform toolkit, Slint offers several features: Firstly, it allows for the separation of the user interface]]></description><link>https://www.codeart.co.ke/p/slint-101-the-basics</link><guid isPermaLink="false">https://www.codeart.co.ke/p/slint-101-the-basics</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Sat, 19 Apr 2025 13:39:25 GMT</pubDate><enclosure url="https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 424w, https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 848w, https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 1272w, https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 1456w" sizes="100vw"><img src="https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png" data-attrs="{&quot;src&quot;:&quot;https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 424w, https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 848w, https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 1272w, https://codeart.co.ke/content/images/2025/04/Slint-101-The-Basics.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Early this year, I mentioned that I was excited about the <a href="https://slint.dev/">Slint</a> development and that it was a toolkit on top of my watchlist this year. Refer to my previous post below.</p><blockquote><h4><a href="https://codeart.co.ke/new-year-new-tech-2025/">New Year: Slint, PocketBase, Rust, and C++; My watchlist</a></h4></blockquote><div><hr></div><p>What is <a href="https://slint.dev/">Slint</a>? Slint is a cross-platform UI toolkit written in Rust with language bindings for C++, JavaScript, Python, and much more. As a cross-platform toolkit, Slint boasts of a couple of features:</p><ul><li><p>Separation between the UI and the business logic: Slint comes with its DSL called <code>slint</code> which allows writing UI and connecting it to the business logic written in our preferred supported language.</p></li><li><p>Lightweight: Slint runs on both modern computers and small microcontrollers, with the Slint runtime fitting within 300 KiB of RAM.</p></li><li><p>Native: Slint compiles to the native binary, which is excellent for performance.</p></li><li><p>And much more!</p></li></ul><div><hr></div><p>Checkout a full walkthrough of Slint on our youtube channel below.</p><div class="captioned-image-container"><figure><div id="youtube2-qP8SFP3qSEo" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;qP8SFP3qSEo&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/qP8SFP3qSEo?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><figcaption class="image-caption"></figcaption></figure></div><p>Youtube Video</p><div><hr></div><p>Hope you find the video helpful. If you have any question, feel free to reach out! Cheers!</p>]]></content:encoded></item><item><title><![CDATA[Extending PocketBase with JavaScript & Go: Custom API Routes and Logic]]></title><description><![CDATA[You&#8217;ve seen how PocketBase can simplify backend development with its one-file magic.]]></description><link>https://www.codeart.co.ke/p/extending-pocketbase-custom-routes-logic</link><guid isPermaLink="false">https://www.codeart.co.ke/p/extending-pocketbase-custom-routes-logic</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Mon, 31 Mar 2025 18:22:44 GMT</pubDate><enclosure url="https://codeart.co.ke/content/images/2025/03/extending-pb.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://codeart.co.ke/content/images/2025/03/extending-pb.jpg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 424w, https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 848w, https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 1272w, https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 1456w" sizes="100vw"><img src="https://codeart.co.ke/content/images/2025/03/extending-pb.jpg" data-attrs="{&quot;src&quot;:&quot;https://codeart.co.ke/content/images/2025/03/extending-pb.jpg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Extending pocketbase in Go &amp; JS&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Extending pocketbase in Go &amp; JS" title="Extending pocketbase in Go &amp; JS" srcset="https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 424w, https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 848w, https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 1272w, https://codeart.co.ke/content/images/2025/03/extending-pb.jpg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Extending pocketbase in Go &amp; JS</figcaption></figure></div><p>You&#8217;ve seen how PocketBase can simplify backend development with its one-file magic. But what if your project needs more &#8212; custom routes, database logic, or deeper control over how things run?</p><p>In this follow-up, we&#8217;ll dive into how to extend PocketBase with JavaScript (or Go) to create a backend that truly fits your business needs.</p><div><hr></div><blockquote><h4><a href="https://codeart.co.ke/pocketbase-one-file-backend/">PocketBase: The Lightweight, One-File Backend You Didn&#8217;t Know You Needed</a></h4></blockquote><div><hr></div><h1>Extending PocketBase</h1><p>The big question is, why would you want to extend PocketBase? Or more so, what's even the meaning of 'extend'? Let's have a look:</p><blockquote><p>English defines the term 'extend' by:<br>- to make available<br>- to increase the scope, meaning, or application of<br>Source: <a href="https://www.merriam-webster.com/dictionary/extend">https://www.merriam-webster.com/dictionary/extend</a></p></blockquote><p>By the literal definition, extending PocketBase means adding the scope, functionality, or amending the existing functionality to act in a particular way.</p><h2>Why extend PocketBase?</h2><p>There are a ton of reasons why I would think of extending any software in existence, not just PocketBase. As the docs would put it;</p><blockquote><p>... PocketBase can be used as a framework which enables you to write your own custom app business logic in Go or JavaScript and still have a portable backend at the end.</p></blockquote><p>The essence of extending PocketBase is to customize and fit the functionality of PocketBase into your business context. I think of PocketBase as a canvas that you can tune to fit the design in mind. Here are some context-specific scenarios I would extend PocketBase:</p><ul><li><p><a href="https://pocketbase.io/docs/go-routing/">Adding custom routes</a>: PocketBase creates API routes for record CRUD operations as well as authentication needs. However, you may need to have some routes to handle business needs, like <em>an endpoint to compute reports</em> or <em>bulk import/export data from your database</em>, etc.</p></li><li><p><a href="https://pocketbase.io/docs/go-event-hooks/">Binding to event hooks and intercepting responses</a>: Pocketbase has several hooks, like app hooks, mailer hooks, real-time hooks, record model hooks, collection model hooks, request hooks, and base model hooks. These hooks allow us to modify the default process by checking user input, formatting data, removing data, etc.</p></li><li><p><a href="https://pocketbase.io/docs/go-console-commands/">Register custom console commands</a>: If you like playing with the PocketBase command-line utility, you may need to add some cmd commands to invoke your business logic. For instance, maybe migrate new data after installation or export existing data into JSON or even SQL?</p></li></ul><p>There is quite a lot that can be added to PocketBase; check the docs section on <a href="https://pocketbase.io/docs/go-overview/">Go</a> and <a href="https://pocketbase.io/docs/js-overview/">Javascript</a> extending sections. Now that we&#8217;ve looked at why you might want to extend PocketBase, let&#8217;s talk about how you can do it &#8212; and which language might be the better fit for your use case.</p><h2>Extend with Go or JavaScript?</h2><p>One of the things to think about beforehand is the language to use to extend PocketBase. As the docs note, you can use PocketBase as a framework in Go or make use of the JavaScript SDK. Each has its own pros and cons. Let's have a look:</p><h3>Extending with Go</h3><p>PocketBase is written in Go, so if you have some basic knowledge in Go, you may find this option more applicable. Beware that you shall be building PocketBase, so you have lots of flexibility. For instance, you can add any 3rd party library to add any kind of functionality you need. In contrast, the Go APIs are verbose and may take time to master well.</p><blockquote><h4><a href="https://pocketbase.io/docs/go-overview/">PocketBase - Open Source backend in 1 file</a></h4></blockquote><h3>Extending with JavaScript</h3><p>In contrast with the Go approach, using JavaScript entails using the standard-built PocketBase binary. This helps you avoid the hassle of building the binary package, which, if you are using a tiny VPS, may take a couple of minutes, depending on the 3rd party packages added. A big plus here is, if you have knowledge in JavaScript, this would be the best place to drop your knowledge.</p><p>However, note that PocketBase uses the <a href="https://github.com/dop251/goja">Goja</a> module for loading and executing JavaScript, which lacks some functionalities unlike Node.js. As such, beware of some inherent limitations like missing concurrent execution using <code>setTimeout</code> and <code>setInterval</code>, support for Common JS modules (CJS), and the unique handler scopes for hooks, which make sharing variables outside the handler hard.</p><blockquote><h4><a href="https://pocketbase.io/docs/js-overview/">PocketBase - Open Source backend in 1 file</a></h4></blockquote><p>Something to keep in mind is that, with the embedded Goja package, browser-specific dependencies like <code>fs, window, etc</code> are not supported. As such, any 3rd-party modules that also depend on the same will not work.</p><p>Despite these limitations, JavaScript is still a powerful and accessible option for extending PocketBase &#8212; so let&#8217;s walk through what that actually looks like in practice.</p><h2>How do we extend PocketBase with JavaScript?</h2><p>Picking up from where we left in our <a href="https://codeart.co.ke/pocketbase-one-file-backend/">last blog</a>, your PocketBase directory should be structured as below:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://codeart.co.ke/content/images/2025/03/image-12.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://codeart.co.ke/content/images/2025/03/image-12.png 424w, https://codeart.co.ke/content/images/2025/03/image-12.png 848w, https://codeart.co.ke/content/images/2025/03/image-12.png 1272w, https://codeart.co.ke/content/images/2025/03/image-12.png 1456w" sizes="100vw"><img src="https://codeart.co.ke/content/images/2025/03/image-12.png" width="1479" height="312" data-attrs="{&quot;src&quot;:&quot;https://codeart.co.ke/content/images/2025/03/image-12.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:312,&quot;width&quot;:1479,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Current directory structure for PocketBase&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Current directory structure for PocketBase" title="Current directory structure for PocketBase" srcset="https://codeart.co.ke/content/images/2025/03/image-12.png 424w, https://codeart.co.ke/content/images/2025/03/image-12.png 848w, https://codeart.co.ke/content/images/2025/03/image-12.png 1272w, https://codeart.co.ke/content/images/2025/03/image-12.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Current directory structure for PocketBase</figcaption></figure></div><p>Two things before we get started:</p><ul><li><p>Open the folder in Visual Studio Code so that we can add the scripts. Use any editor of your choosing.</p></li><li><p>We'll be launching the pocketbase as a <code>dev</code> so that we can see the debug logs as the app starts. This may be helpful to monitor our hooks.</p></li></ul><blockquote><p>&#9888;&#65039; Note: on UNIX platforms, changing the hooks will trigger the PocketBase to reload. On Windows, you will have to restart PocketBase manually.</p></blockquote><p>In this section, we&#8217;ll explore how to extend PocketBase using JavaScript&#8212;covering topics such as adding new routes, custom database interactions, middleware, and hooks.</p><h3>a. <a href="https://pocketbase.io/docs/js-routing/">Adding New Routes</a></h3><p>One of the primary ways to extend PocketBase is by creating custom API endpoints. Whether you need to aggregate data from various sources, perform specialized computations, or integrate third-party services, adding new routes gives you full control over your API. For example, you can define a new GET endpoint that fetches records from a specific collection:</p><pre><code>// Example: Adding a custom GET route to PocketBase
routerAdd('GET', '/org/public-endpoint', (e) =&gt; {
    // Interact with the internal database, do your
    // aggregation and return data if successful
    e.json(200, { success: true })
});

// register "POST /org/secret-endpoint" route 
// (allowed only for authenticated users)
routerAdd("POST", "/org/secret-endpoint", (e) =&gt; {
    // do something ...
    return e.json(200, { "success": true })
}, $apis.requireAuth())

</code></pre><p>In this snippet, we add a route <code>/org/public-endpoint</code> and <code>/org/private-endpoint</code> allow for interaction with the database layer, with later requiring user log in. This approach encapsulates custom business logic without modifying the core system.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://codeart.co.ke/content/images/2025/03/image-13.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://codeart.co.ke/content/images/2025/03/image-13.png 424w, https://codeart.co.ke/content/images/2025/03/image-13.png 848w, https://codeart.co.ke/content/images/2025/03/image-13.png 1272w, https://codeart.co.ke/content/images/2025/03/image-13.png 1456w" sizes="100vw"><img src="https://codeart.co.ke/content/images/2025/03/image-13.png" width="2000" height="1128" data-attrs="{&quot;src&quot;:&quot;https://codeart.co.ke/content/images/2025/03/image-13.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1128,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Code sample execution output&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Code sample execution output" title="Code sample execution output" srcset="https://codeart.co.ke/content/images/2025/03/image-13.png 424w, https://codeart.co.ke/content/images/2025/03/image-13.png 848w, https://codeart.co.ke/content/images/2025/03/image-13.png 1272w, https://codeart.co.ke/content/images/2025/03/image-13.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Code sample execution output</figcaption></figure></div><p>Once your routes are in place, the next natural step is working directly with the database to handle more advanced operations. So, let's take a look.</p><h3>b. <a href="https://pocketbase.io/docs/js-database/">Custom Database Interactions</a></h3><p>While PocketBase&#8217;s integrated database is designed for speed and simplicity, many applications require more advanced data manipulation. Using the PocketBase JavaScript SDK, you can execute complex queries, apply filters, sort data, and even perform batch updates. Consider the following example:</p><pre><code>// register "POST /org/secret-endpoint" route (allowed only for authenticated users)
routerAdd("POST", "/org/secret-endpoint", (e) =&gt; {
    // Other code here ...

    // Lets run in a transaction block
    $app.runInTransaction((txApp) =&gt; {
      // update a record
      const record = txApp.findRecordById("articles", "RECORD_ID")
      record.set("status", "active")
      txApp.save(record) // Update Record

      // Create a record
      let collection = $app.findCollectionByNameOrId("&lt;some collection&gt;")
      let record = new Record(collection)
      record.set("title", "Lorem ipsum")
      record.set("active", true)
      txApp.save(record) // Save Record
  
      // run a custom raw query (doesn't fire event hooks)
      txApp.db().newQuery("DELETE FROM articles WHERE status = 'pending'").execute()
  })
    return e.json(200, { "success": true })
}, $apis.requireAuth())</code></pre><p>Here, we are making use of transactions to ensure the changes are only committed if no error is thrown, lest we have a <code>rollback</code>. We update an existing record, create a new record, and delete another record, all operations that must execute successfully before we commit the changes to the database.</p><p>This example demonstrates how you can leverage the SDK to perform refined data operations&#8212;tailoring data retrieval to fit your application&#8217;s unique needs.</p><h3>c. <a href="https://pocketbase.io/docs/js-routing/#middlewares">Integrating Middlewares</a></h3><p>Beyond adding routes and custom database interactions, PocketBase supports middlewares, enabling you to inject logic at critical points in your application workflow. Middlewares can be essential in validating data before proceeding to the next step or even checking authentication and much more. Below is a simple middleware added to the <code>/some/route</code> route, any logical condition can be done there to decide if code execution should proceed to <code>e.next()</code> or return back to the client.</p><pre><code>// Attach middleware to a single route
// "GET /some/route"
routerAdd("GET", "/some/route", (e) =&gt; {
    // Execute some db query, ...
    return e.string(200, "Hello!")
}, (e) =&gt; {
    // Do some checks here ...
    // Your custome middleware ...
    return e.next()
})</code></pre><p>Utilizing middleware ensures that your customizations remain modular and centralized, which is especially beneficial for maintaining data integrity and consistency across your application.</p><p>PocketBase out of the box offers some middlewares for use. These include:</p><pre><code>// Require the request client to be unauthenticated (aka. guest).
$apis.requireGuestOnly()

// Require the request client to be authenticated
// (optionally specify a list of allowed auth collection names, default to any).
$apis.requireAuth(optCollectionNames...)

// Require the request client to be authenticated as superuser
// (this is an alias for $apis.requireAuth("_superusers")).
$apis.requireSuperuserAuth()

// Require the request client to be authenticated as superuser OR
// regular auth record with id matching the specified route parameter (default to "id").
$apis.requireSuperuserOrOwnerAuth(ownerIdParam)

// Changes the global 32MB default request body size limit (set it to 0 for no limit).
// Note that system record routes have dynamic body size limit based on their collection field types.
$apis.bodyLimit(limitBytes)

// Compresses the HTTP response using Gzip compression scheme.
$apis.gzip()

// Instructs the activity logger to log only requests that have failed/returned an error.
$apis.skipSuccessActivityLog()</code></pre><p>With your extensions in place &#8212; routes, data logic, and middleware &#8212; it's important to consider a few best practices to ensure your setup remains maintainable and secure over time.</p><h4>Best Practices for Extending PocketBase</h4><ul><li><p><strong>Modular Code Organization:</strong> Separate your custom routes, hooks, and database logic into distinct modules. This practice not only makes your code more maintainable but also facilitates future scalability.</p></li><li><p><strong>Robust Error Handling:</strong> Implement comprehensive error handling within your custom endpoints and hooks to ensure that exceptions do not cascade into critical failures.</p></li><li><p><strong>Security Considerations:</strong> Always validate and sanitize incoming data, particularly in routes that interact directly with your database. This is crucial for preventing common vulnerabilities such as injection attacks.</p></li><li><p><strong>Clear Documentation:</strong> Maintain thorough documentation for each extension. This aids both current team members and future developers in understanding the purpose and functionality of your customizations.</p></li></ul><h2>Conclusion</h2><p>Whether it&#8217;s by adding new routes to expose custom logic, leveraging the SDK for complex database interactions, or incorporating middleware and hooks to manage application flow, these techniques empower you to build a more dynamic and responsive system. Embrace these extension strategies to make PocketBase not just a backend service but a flexible platform that evolves with your project&#8217;s needs.</p><p>Similar to JavaScript, Go can be utilized in a similar manner to extend the core functionality. Whichever tool you pick, analyze the options and pick what works best for you and the team.</p><div><hr></div><p>Have any questions, suggestions, or concerns? Please let me know below. Cheers!</p>]]></content:encoded></item><item><title><![CDATA[PocketBase: The Lightweight, One-File Backend You Didn’t Know You Needed]]></title><description><![CDATA[There are times in development when you just wish the tooling could stay out of your way.]]></description><link>https://www.codeart.co.ke/p/pocketbase-one-file-backend</link><guid isPermaLink="false">https://www.codeart.co.ke/p/pocketbase-one-file-backend</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Thu, 27 Mar 2025 18:09:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/dcbc8c5d-e058-4062-b1d4-11e4f265c367_2048x1132.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!63Qv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!63Qv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 424w, https://substackcdn.com/image/fetch/$s_!63Qv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 848w, https://substackcdn.com/image/fetch/$s_!63Qv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 1272w, https://substackcdn.com/image/fetch/$s_!63Qv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!63Qv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;PocketBase feature snippet from https://pocketbase.io &quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="PocketBase feature snippet from https://pocketbase.io " title="PocketBase feature snippet from https://pocketbase.io " srcset="https://substackcdn.com/image/fetch/$s_!63Qv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 424w, https://substackcdn.com/image/fetch/$s_!63Qv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 848w, https://substackcdn.com/image/fetch/$s_!63Qv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 1272w, https://substackcdn.com/image/fetch/$s_!63Qv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b6ce4d2-e7f1-4213-91bc-45a6cf921557_2048x1132.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">PocketBase cover image</figcaption></figure></div><p>There are times in development when you just wish the tooling could stay out of your way. You&#8217;re building a front-end &#8212; maybe a mobile app, maybe embedded &#8212; and all you want is to test some functionality: a login screen, some data flows, maybe a bit of access control. But before you know it, you&#8217;ve spun up yet another backend project, configured auth, debugged token issues, and lost half a day to infrastructure rather than solving your actual problem.</p><p>This happens to a lot of us. We start with a simple idea and end up building supporting systems that spiral beyond what we originally intended.</p><p>Sometimes, you don&#8217;t need the full stack. Sometimes, you just want something that works &#8212; fast, local, and lightweight.</p><blockquote><p>"Everything should be made as simple as possible, but not simpler."<br><br>&#8212; Albert Einstein</p></blockquote><p>That&#8217;s where PocketBase comes in.</p><div><hr></div><h2>What's <a href="https://pocketbase.io/">PocketBase</a>?</h2><p>The Pocketbase team describes it as <em><strong>an open-source backend in 1 file</strong></em>. Yes, one single file. It's a complete <em>(complete can be relative; keep that in mind) <strong>Backend as a Service (BaaS)</strong></em> solution that can be spun up to offer a fully fledged backend for mobile, desktop, web, and even embedded solutions.</p><p>Being a lightweight and performant backend solution, PocketBase makes use of SQLite as the storage database, which allows embedding the database into the final executable. For some use cases, this may be desirable, but for others, this may not be the database we desire, so there are trade-offs.</p><h3>Why PocketBase?</h3><p>PocketBase offers some eye-catching features out of the box without much tweaking. These are:</p><ul><li><p><em><strong>Full backend in 1 file</strong></em>: This may not be a selling point to others, but it's a pretty big deal if you know. No messy <code>node-modules</code> folder and the million other files you need to run your node backend. PocketBase is written in Go, a statically typed and compiled language, which converts all user code into a single binary file. This file can be copied over to a target PC and run as is (if the architecture matches, of course), and all features are available for use.</p></li><li><p><em><strong>Real-time database</strong></em>: Once in a while, your project may need real-time subscription to record changes in your database. Data changes in the database emit events in which all subscribed clients are notified about.</p></li><li><p><em><strong>Authentication: </strong></em>By default, Pocketbase provides multiple methods of user authentication, including the standard username/password and OAuth protocols. Yes, you'll need to provide some credentials for the auth to work, but everything else is already implemented for you. Additionally, there are row-level access rules for record listing (List/Search Rules), record viewing (View rule), record creation (Create rule), record update (Update rule), and record delete (Delete rule), which allow for specifying rules users have to meet to perform the different tasks on the backend.</p></li><li><p><em><strong>File Storage</strong></em>: By default, PocketBase provides local storage for all files uploaded to the server and conveniently generates thumbnails where applicable. There is an additional option to connect to an S3 bucket for external file storage. File access can be regulated to public or token-based access to add a level of security to some files.</p></li><li><p><em><strong>Extensibility</strong></em>: PocketBase functionality can be extended using Go or JavaScript or used as is. This feature allows us to add new functionalities, modify existing ones, or even do things like provide your own database driver for specific use cases.</p></li><li><p><em><strong>APIs &amp; SDK</strong></em>: By default, PocketBase creates a full CRUD API for every table (collection) you create. This allows querying the data via the API or any supported SDKs, allowing connection to front-end applications or 3rd party applications.</p></li><li><p>Admin Dashboard: The backend comes with a beautiful admin dashboard, which allows admin management, collections, record operations, and much more!</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dE66!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dE66!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 424w, https://substackcdn.com/image/fetch/$s_!dE66!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 848w, https://substackcdn.com/image/fetch/$s_!dE66!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 1272w, https://substackcdn.com/image/fetch/$s_!dE66!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dE66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png" width="1715" height="754" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:754,&quot;width&quot;:1715,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Admin dashboard from the demo site at https://pocketbase.io/demo/&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Admin dashboard from the demo site at https://pocketbase.io/demo/" title="Admin dashboard from the demo site at https://pocketbase.io/demo/" srcset="https://substackcdn.com/image/fetch/$s_!dE66!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 424w, https://substackcdn.com/image/fetch/$s_!dE66!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 848w, https://substackcdn.com/image/fetch/$s_!dE66!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 1272w, https://substackcdn.com/image/fetch/$s_!dE66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F675fe964-b6a9-4872-8918-31e6a5bbedb4_1715x754.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Admin dashboard from the demo site at <a href="https://pocketbase.io/demo/">https://pocketbase.io/demo/</a></figcaption></figure></div><h2>Getting Started</h2><p>So,<em> how do you get and make use of PocketBase</em>? First, navigate to the PocketBase documentation below, at the time of writing, latest version being v0.26.4;</p><blockquote><h4><a href="https://pocketbase.io/docs/">PocketBase - Open Source backend in 1 file</a></h4></blockquote><p>Whether your current OS is<em> Windows, Mac, </em>or<em> Linux</em> on <em>x86 </em>or<em> ARM64</em>, download the corresponding binary zip file to your PC as shown below. Alternatively, navigate to the <a href="https://github.com/pocketbase/pocketbase/releases">PocketBase release page</a> and get the platform release binary from there.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cC17!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cC17!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 424w, https://substackcdn.com/image/fetch/$s_!cC17!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 848w, https://substackcdn.com/image/fetch/$s_!cC17!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 1272w, https://substackcdn.com/image/fetch/$s_!cC17!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cC17!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png" width="1347" height="960" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:960,&quot;width&quot;:1347,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Pocketbase download section&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Pocketbase download section" title="Pocketbase download section" srcset="https://substackcdn.com/image/fetch/$s_!cC17!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 424w, https://substackcdn.com/image/fetch/$s_!cC17!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 848w, https://substackcdn.com/image/fetch/$s_!cC17!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 1272w, https://substackcdn.com/image/fetch/$s_!cC17!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc2b11b4-1d44-48ad-843a-be62b2384ff2_1347x960.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Pocketbase download section</figcaption></figure></div><p>Once downloaded, use your favorite zip tool to unzip the archive to your desired directory. This should give three files as shown below. Of concern, we'll only use the <code>pocketbase</code> binary file.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7KdS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7KdS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 424w, https://substackcdn.com/image/fetch/$s_!7KdS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 848w, https://substackcdn.com/image/fetch/$s_!7KdS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 1272w, https://substackcdn.com/image/fetch/$s_!7KdS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7KdS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png" width="697" height="136" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7174965d-6a37-4603-9671-9850a478882f_697x136.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:136,&quot;width&quot;:697,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Extracted PocketBase files on Windows&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Extracted PocketBase files on Windows" title="Extracted PocketBase files on Windows" srcset="https://substackcdn.com/image/fetch/$s_!7KdS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 424w, https://substackcdn.com/image/fetch/$s_!7KdS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 848w, https://substackcdn.com/image/fetch/$s_!7KdS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 1272w, https://substackcdn.com/image/fetch/$s_!7KdS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7174965d-6a37-4603-9671-9850a478882f_697x136.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Extracted PocketBase files on Windows</figcaption></figure></div><h3>Starting the server</h3><p>Starting the PocketBase server is pretty simple. As the docs say, execute the binary and pass the <code>serve</code> command argument to it as shown below. This will spin up the PocketBase server on the default port <code>8090</code> which we can override if need be. Being the first time spinning the server, a couple of directories will be created to store the database data, migration scripts, and file assets.</p><pre><code>cd &lt;unzipped directory&gt;
./pocketbase serve
</code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cB5v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cB5v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 424w, https://substackcdn.com/image/fetch/$s_!cB5v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 848w, https://substackcdn.com/image/fetch/$s_!cB5v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 1272w, https://substackcdn.com/image/fetch/$s_!cB5v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cB5v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png" width="1078" height="457" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:457,&quot;width&quot;:1078,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Starting pocketbase server&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Starting pocketbase server" title="Starting pocketbase server" srcset="https://substackcdn.com/image/fetch/$s_!cB5v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 424w, https://substackcdn.com/image/fetch/$s_!cB5v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 848w, https://substackcdn.com/image/fetch/$s_!cB5v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 1272w, https://substackcdn.com/image/fetch/$s_!cB5v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847c6221-2b2d-4990-a72b-4fa8ae035ad0_1078x457.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Starting pocketbase server</figcaption></figure></div><p>By default, the server in dev mode spins up the admin panel on our default browser for us to create a default admin user. This is the admin user we'll use for logging into the admin panel going forward.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cGvC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cGvC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 424w, https://substackcdn.com/image/fetch/$s_!cGvC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 848w, https://substackcdn.com/image/fetch/$s_!cGvC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 1272w, https://substackcdn.com/image/fetch/$s_!cGvC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cGvC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png" width="2000" height="1169" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1169,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The default admin panel after logging in&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The default admin panel after logging in" title="The default admin panel after logging in" srcset="https://substackcdn.com/image/fetch/$s_!cGvC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 424w, https://substackcdn.com/image/fetch/$s_!cGvC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 848w, https://substackcdn.com/image/fetch/$s_!cGvC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 1272w, https://substackcdn.com/image/fetch/$s_!cGvC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0eddb0e-4d13-4170-beb5-038901827542_2826x1652.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The default admin panel after logging in</figcaption></figure></div><p>From the admin panel, we can:</p><ul><li><p>Create New Collections: This is new tables in SQL terms, which will contain the record fields. Each collection can additionally specify the access rules; by default, only admins can perform CRUD on any collection data. There are 3 types of collections:</p><ul><li><p><em>Base Type</em>: Any general collection; this type adds a <em><code>unique record ID</code></em> and <code>created</code> and <code>updated</code> timestamps.</p></li><li><p><em>Auth Type</em>: These records allow for logging into your applications. This template extends the <code>Base Type</code> with fields like <code>password, tokenKey, email, verified, emailVisibility, etc</code> which help in capturing user login information.</p></li><li><p><em>View Type</em>: Analogous to the SQL View type, because it's exactly that. A read-only view created by writing an SQL statement.</p></li></ul></li><li><p>Create/Update/Delete Records: We can perform CRUD operations on data on existing collections.</p></li><li><p>Manage Access Rules: The create collections drawer has two tabs or more, the second being <code>API Rules</code> in which we define conditional statements that are evaluated for the 5 rules <em>(listRule, viewRule, createRule, updateRule, and deleteRule)</em>. Pocketbase offers some handy macros to access other collections and records, as well as request information to determine access metrics for the current user request. Check <a href="https://pocketbase.io/docs/api-rules-and-filters/">here</a> for more information and syntax.</p></li><li><p>Access Logs: PocketBase provides a view to check logs with a default 5-day retention period. You can change the log level from the gear icon here to set the kind of information to be logged.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QvWE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QvWE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 424w, https://substackcdn.com/image/fetch/$s_!QvWE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 848w, https://substackcdn.com/image/fetch/$s_!QvWE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 1272w, https://substackcdn.com/image/fetch/$s_!QvWE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QvWE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png" width="1127" height="697" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:697,&quot;width&quot;:1127,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Log view on the admin panel&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Log view on the admin panel" title="Log view on the admin panel" srcset="https://substackcdn.com/image/fetch/$s_!QvWE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 424w, https://substackcdn.com/image/fetch/$s_!QvWE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 848w, https://substackcdn.com/image/fetch/$s_!QvWE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 1272w, https://substackcdn.com/image/fetch/$s_!QvWE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17037daf-280a-43e4-a81a-5c9ed6659d40_1127x697.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Log view on the admin panel</figcaption></figure></div><ul><li><p>Application Settings: Application configuration like application <em>name, URL, SMTP settings, and backup jobs </em>as well as<em> collection import/export</em> are all housed here.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Pnhs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Pnhs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 424w, https://substackcdn.com/image/fetch/$s_!Pnhs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 848w, https://substackcdn.com/image/fetch/$s_!Pnhs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 1272w, https://substackcdn.com/image/fetch/$s_!Pnhs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Pnhs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png" width="1130" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1130,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Pnhs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 424w, https://substackcdn.com/image/fetch/$s_!Pnhs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 848w, https://substackcdn.com/image/fetch/$s_!Pnhs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 1272w, https://substackcdn.com/image/fetch/$s_!Pnhs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2668e9c-261e-4360-be1c-bbf96d22cfe0_1130x695.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p><em>Admin Accounts</em>: We can also manage admin accounts from this pane on the bottom left side menu icon.</p></li></ul><h3>So how does it all work?</h3><p>When we spin up the PocketBase server, the following directories will be created:</p><ul><li><p><code>/pb_data</code> : This directory will have the <code>data.db</code> file to store the application data, an <code>auxiliary.db</code> file to store log data, and a<code>/storage/</code> folder to store record files if we are keeping them in the local directory.</p></li><li><p><code>/pb_migrations</code> : Created once we modify collections while running in development mode. Here, any changes on the collections are recorded into a <code>*.js</code> file which can be pushed to a GitHub repo, and when we pull on another server/PC, starting the server recreates the collections from the migration scripts here.</p></li><li><p><code>/pb_public</code> : Not created by default, but we can create and put any static files we want the server to serve. For instance, put here the <code>.html</code> and <code>.css</code> files to have them served.</p></li><li><p><code>/pb_hooks</code> : Not created by default, but here we can write <code>*.pb.js</code> scripts that extend the functionality of PocketBase. These scripts can add new routes, perform specific actions before writing data to the database, etc. Check on <a href="https://pocketbase.io/docs/use-as-framework/">extending PocketBase</a> in the docs on the full feature list we can do here.</p></li></ul><p>With such a setup, we can copy the whole structure into a new computer and have the same functionality on the go.</p><h2>How does it compare?</h2><p>Of course, in the world of <code>BaaS</code> , there are several offerings. Of notable mentions:</p><ul><li><p><em><a href="https://firebase.google.com/">Google Firebase</a></em>: Owned by Google, offering a free tier to some level, then a pay-per-consumption model kicks in. Uses two database kinds, Firestore and real-time database (JSON database). In terms of usability, you'll get lots of integration with the tons of Google services, which might be desirable but, of course, will be vendor-locked, and you can't host it yourself.</p></li><li><p><a href="https://appwrite.io/">AppWrite</a>: A self-hostable BaaS offering a NoSQL database API but running MariaDB/MySQL under the hood. Has most of the features, but direct database access is a bit lacking, and I believe it's for a reason.</p></li><li><p><em><a href="https://supabase.com/">SupaBase</a></em>: Similar to PocketBase in terms of using a relational database and being self-hostable. The difference here is that SupaBase uses a PostgreSQL database, which can come in handy in cases where we need horizontal scaling and not just vertical scaling. If you feel PocketBase is not enough for you, this can be a better go-to for self-hosted options. Of course, it's more resource-hungry compared to PocketBase.</p></li></ul><p>There are tons of choices, but it all depends on the task at hand. A balance between the effort needed, features desired, processing, etc. For instance, hosting AppWrite and SupaBase requires containerization, which adds a layer of complexity to set up but also hides a whole lot of mess when setting it up. Both are massive projects; as such, there are lots of moving pieces to consider, so containerization helps in such cases.</p><p>So, if you just needed a quick spin-up, I guess you are best sticking with PocketBase. Quick prototyping and fiddling do not need the painful hassle of looking for a hosting provider, learning a bit of Docker, or even messing with Firebase rules; maybe just get the <code>&lt;40mb</code> pocketbase binary, and you are all set.</p><blockquote><p>To every problem, there is a most simple solution. <br>Agatha Christie</p></blockquote><h2>What Next?</h2><p>We'll soon do a walkthrough of setting up collections, record rules, API tests, and lastly extending PocketBase with JavaScript/Go. Meanwhile, play around with the docs, experiment a bit and discover the potential PocketBase can offer to your development journey.</p><div><hr></div><p>I hope this was helpful; let me know your thoughts! Cheers!</p>]]></content:encoded></item><item><title><![CDATA[QML mapToItem vs mapToGlobal—When and How to Use Each]]></title><description><![CDATA[When working with QML, you often need to position UI elements relative to a global or local coordinate system.]]></description><link>https://www.codeart.co.ke/p/qml-maptoitem-vs-maptoglobal-how-to-use-each</link><guid isPermaLink="false">https://www.codeart.co.ke/p/qml-maptoitem-vs-maptoglobal-how-to-use-each</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Fri, 07 Mar 2025 12:29:27 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b5071f20-fb42-403b-b014-3674322c7f2d_1980x1114.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iW1x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iW1x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 424w, https://substackcdn.com/image/fetch/$s_!iW1x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 848w, https://substackcdn.com/image/fetch/$s_!iW1x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!iW1x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iW1x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iW1x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 424w, https://substackcdn.com/image/fetch/$s_!iW1x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 848w, https://substackcdn.com/image/fetch/$s_!iW1x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!iW1x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bd5b76e-c1bf-45bc-99a2-717cbdca30dd_1980x1114.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Image showing a popup window being centered in a laptop screen</figcaption></figure></div><p>When working with QML, you often need to position UI elements relative to a global or local coordinate system. To contextualize it, imagine you have your layout done with a sidebar on the left and the main context view taking over the remaining space.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kf6U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kf6U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kf6U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kf6U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kf6U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kf6U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg" width="1980" height="1114" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1114,&quot;width&quot;:1980,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!kf6U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kf6U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kf6U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kf6U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109852c7-9eae-4604-9f06-86906699477d_1980x1114.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">App layout (sidebar, toolbar, main content area)</figcaption></figure></div><p>Inside the main view, you need to spawn a popup that displays some information or even get user input for processing. A simple way to center your popup would be to manipulate the items `x` and `y` coordinate systems as shown below;</p><pre><code>// Other QML imports here

Popup {
&#9;width: 300
&#9;height: 250
&#9;
&#9;// `app` here is the ID for the root window
&#9;x: (app.width - width)/2
&#9;y: (app.height - height)/2
}

</code></pre><p>As expected, the popup when opened is centered on both the horizontal and vertical axes of the parent view. On closer look, we can see the popups x-offset is larger on the left than on the right side of the popup. The screenshot below shows the effect of adding spacing in a RowLayout containing the SideBar and the MainContentItem. <em>But why isn't the popup centered?</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!84SZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!84SZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 424w, https://substackcdn.com/image/fetch/$s_!84SZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 848w, https://substackcdn.com/image/fetch/$s_!84SZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 1272w, https://substackcdn.com/image/fetch/$s_!84SZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!84SZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png" width="1338" height="1020" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1020,&quot;width&quot;:1338,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!84SZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 424w, https://substackcdn.com/image/fetch/$s_!84SZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 848w, https://substackcdn.com/image/fetch/$s_!84SZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 1272w, https://substackcdn.com/image/fetch/$s_!84SZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d707643-90af-4b19-bf17-9f28c5c953f5_1338x1020.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">App screenshot showing popup being off-center</figcaption></figure></div><p>Remember that the popup centering by setting the x and y value is relative to the parent Item. In this case, we are creating the popup from within the <code>MainContentItem.</code> As such, the calculated x value is does not take into account the presence of the <code>SideBar</code> as well as the <code>RowLayout</code> spacing; hence, the spawned popup is off-center but <code>spacing + sidebar width.</code></p><h3>Quick Fix</h3><p>A common approach I have seen on other codebases (including how I used to do it) is to use the <code>mapToGlobal</code> function to get the global coordinates and calculate the <code>x and y</code> offsets from it. In theory, this approach is correct; however, I've observed several novice errors, including my own. So, a quick solution for the <em>xOffset </em>would be;</p><pre><code>// Other code as before
x: (app.width - width)/2 - ((app.width - width)/2 - mapToGlobal(0,0).x)
// Other code as before
</code></pre><p>What's all that mumbo jumbo? Basically, we are:</p><ul><li><p>Calculating the x center from the parent item using <code>(app.width - width)/2</code></p></li><li><p>We are calculating the difference between the mapped x-position of the <code>(0,0)</code> position of our popup and the global position and the x-center above. This, in theory, should give the offset to apply on the x-side to reposition the popup.</p></li><li><p>Lastly, we subtract the offset from the x-center in step 1. In theory, this should center the popup in the window.</p></li></ul><p>But, looking at the output window, our popup is way off-center. It was even better before, kind of; we have made it worse. Where did we go wrong?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oElz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oElz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 424w, https://substackcdn.com/image/fetch/$s_!oElz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 848w, https://substackcdn.com/image/fetch/$s_!oElz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 1272w, https://substackcdn.com/image/fetch/$s_!oElz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oElz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png" width="1284" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1284,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!oElz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 424w, https://substackcdn.com/image/fetch/$s_!oElz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 848w, https://substackcdn.com/image/fetch/$s_!oElz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 1272w, https://substackcdn.com/image/fetch/$s_!oElz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76641302-97cb-443e-b915-0ef5beb2c024_1284x756.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Popup position after the quick fix</figcaption></figure></div><h2>Understanding mapToGlobal vs mapToItem</h2><p>First, when an app draws its window, there are two coordinate systems at play here. One is the global coordinate relative to the monitor or screen. The next is the local coordinate relative to the app's top-left position, <em>a.k.a., the origin (0,0)</em> or the parent item.</p><p>For <em><strong><a href="https://doc.qt.io/qt-6/qml-qtquick-item.html#mapToGlobal-method">mapToGlobal</a></strong></em>, it converts the given local coordinate into a global screen coordinate. That is, whether the app is full-screen, maximized, or just taking a small portion, the coordinate returned is relative to the screen and not the window/app in question.</p><p>In contrast, <em><strong><a href="https://doc.qt.io/qt-6/qml-qtquick-item.html#mapToItem-method-1">mapToItem</a></strong></em> takes a target item as the first parameter and the coordinates to transform as the second and third parameters. This maps the current item's coordinate position to the item of interest.</p><h2>How do we fix our `perfect` popup centering?</h2><p>Quite simple now that we understand the concepts above. Let's map the popup&#8217;s origin position to the <em>ApplicationWindow</em>'s contentItem to the x &amp; y offsets. The returned offset x and y shall be subtracted from our x-center and y-center, respectively.</p><pre><code>// Other code as before
x: (app.width - width)/2 - mapToItem(app.contentItem, 0,0).x
// Other code as before
</code></pre><p>As noted, `<em><strong>mapToItem</strong></em>` expects an item as a parameter. Our <em><a href="https://doc.qt.io/qt-5/qml-qtquick-window-window.html">Window</a></em> or <em><a href="https://doc.qt.io/Qt-6/qml-qtquick-controls-applicationwindow.html">ApplicationWindow</a></em> is not an item and will throw an error if passed in. To resolve that, access the item within the window, which is usually the `<em><strong>contentItem</strong></em>`.</p><h2>Conclusion</h2><p>A similar approach can be used to apply the offset on the y-axis. I hope you found this informative; let me know how you would have done the alignment.</p><p>Cheers!</p>]]></content:encoded></item><item><title><![CDATA[Pre vs. Post Increment & Decrement Operator in C++]]></title><description><![CDATA[If you've worked with C++, even at a basic level, you've likely encountered pre-increment (++x), pre-decrement (--x), post-increment (x++), and post-decrement (x--).]]></description><link>https://www.codeart.co.ke/p/pre-post-inc-dec-cpp</link><guid isPermaLink="false">https://www.codeart.co.ke/p/pre-post-inc-dec-cpp</guid><dc:creator><![CDATA[Allan K. Koech]]></dc:creator><pubDate>Thu, 06 Feb 2025 20:10:37 GMT</pubDate><enclosure url="https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 424w, https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 848w, https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 1272w, https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 1456w" sizes="100vw"><img src="https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png" data-attrs="{&quot;src&quot;:&quot;https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;pre vs post increment/decrement operator in c++&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="pre vs post increment/decrement operator in c++" title="pre vs post increment/decrement operator in c++" srcset="https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 424w, https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 848w, https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 1272w, https://codeart.co.ke/content/images/2025/02/pre-post-inc-dec-cpp.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>If you've worked with C++, even at a basic level, you've likely encountered pre-increment (<code>++x</code>), pre-decrement (<code>--x</code>), post-increment (<code>x++</code>), and post-decrement (<code>x--</code>). While these operators may behave similarly in C, they have distinct differences in C++.</p><div><hr></div><p>For reference</p><blockquote><h4><a href="https://en.cppreference.com/w/cpp/language/operator_incdec">Increment/decrement operators - cppreference.com</a></h4></blockquote><div><hr></div><h2>Pre-Increment Operator (<code>++x</code>)</h2><p>Think of this operator as simply adding <code>1</code> to <code>x</code>. For example:</p><div class="captioned-image-container"><figure><pre><code>int main() {
    int x = 0;

    // Equivalent to y = x + 1;
    int y = ++x;

    // Prints `1`
    std::cout &lt;&lt; y &lt;&lt; std::endl;
}
</code></pre><figcaption class="image-caption"></figcaption></figure></div><p>pre-increment operator c++ code block</p><p>Here, <code>x</code> is incremented first, and then the new value is assigned to <code>y</code>.</p><h2>Post-Increment Operator (<code>x++</code>)</h2><p>Unlike pre-increment, the post-increment operator returns the original value of <code>x</code> before incrementing it. As cppreference explains, this operator creates a temporary copy of the object, then increments the original.</p><div class="captioned-image-container"><figure><pre><code>int main() {
    int x = 0;
    int y = x++;

    // Prints `0`
    std::cout &lt;&lt; y &lt;&lt; std::endl;

    // Prints `1`
    std::cout &lt;&lt; x &lt;&lt; std::endl;
}
</code></pre><figcaption class="image-caption"></figcaption></figure></div><p>post-increment operator c++ code block</p><p>Why is the output <code>0</code> instead of <code>1</code>? Let's break it down:</p><ol><li><p>A copy of <code>x</code> is created (both <code>x</code> and its copy are <code>0</code>).</p></li><li><p><code>x</code> is incremented to <code>1</code>.</p></li><li><p><code>y</code> is assigned the initial value of <code>x</code> (which was <code>0</code>).</p></li><li><p>As a result, <code>x</code> becomes <code>1</code>, while <code>y</code> remains <code>0</code>.</p></li></ol><p>A similar approach works for the pre- and post- decrement operators.</p><h2>When to Use Pre- vs. Post-Increment/Decrement</h2><p>It depends on what you need from your code.</p><ul><li><p>If you need the variable to be incremented/decremented before assignment or evaluation, use <strong>pre-increment/decrement</strong> (<code>++x</code>, <code>--x</code>).</p></li><li><p>If you need to retain the original value before modifying it, use <strong>post-increment/decrement</strong> (<code>x++</code>, <code>x--</code>).</p></li></ul><h2>Operator Overloading</h2><p>C++ allows operator overloading, so both pre- and post-increment/decrement can be customized for user-defined types. The Standard Library (STL) leverages this for types like <code>std::atomic&lt;T&gt;</code> and <code>std::chrono::duration&lt;Rep, Period&gt;</code>, enabling them to support these operators seamlessly.</p><div><hr></div>]]></content:encoded></item></channel></rss>