<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>vectronic</title>
        <link>https://vectronic.io/</link>
        <description>Blog posts from vectronic</description>
        <language>en-gb</language>
        <managingEditor>hello.vectronic@gmail.com (vectronic)</managingEditor>
        <webMaster>hello.vectronic@gmail.com (vectronic)</webMaster>
        <lastBuildDate>Tue, 21 Oct 2025 00:00:00 +0000</lastBuildDate>
        <atom:link href="https://vectronic.io/index.xml" rel="self" type="application/rss+xml" />
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>First Real Project on the Pocket NC</title>
            <link>https://vectronic.io/posts/first-real-project-on-the-pocket-nc/</link>
            <pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/first-real-project-on-the-pocket-nc/</guid>
            <description>&lt;p&gt;The first &amp;ldquo;real world&amp;rdquo; project on the Pocket NC was to create 2 replacement Oilite bushes for the mains powered Synchron motor in a 1940&amp;rsquo;s &lt;a href=&#34;https://kit-cat.com/pages/history&#34;&gt;Kit Cat Clock&lt;/a&gt;.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-real-project-on-the-pocket-nc/images/closeup.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;I&amp;rsquo;m much more familiar with Fusion 360 and was able to generate a program with 9 operations using 4 tools:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-real-project-on-the-pocket-nc/images/toolpaths.jpg&#34; width=&#34;75%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;I used the &lt;a href=&#34;https://vers.ge/en/blog/user-guides/wlr-v8&#34;&gt;Vers Wireless Touch Probe&lt;/a&gt; to setup the work coordinates, but just did the touch off manually. I also used it connected to the receiver instead of wirelessly as the receiver is yet to be integrated into the Pocket NC tool length sensor. So the next step is definitely to integrate with the hardware and automate within GCode.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Anyway, less words, more pictures!&lt;/p&gt;
&lt;p&gt;Here is a video showing an overview of the setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iPad for local control&lt;/li&gt;
&lt;li&gt;computer for more detailed configuration, Fusion work and management of the machine view videos&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;video-container&#34;&gt;
   &lt;iframe
      credentialless
      allowfullscreen
      sandbox=&#34;allow-scripts allow-same-origin&#34;
      allow=&#34;accelerometer &#39;none&#39;; ambient-light-sensor &#39;none&#39;; autoplay &#39;none&#39;; battery &#39;none&#39;; bluetooth &#39;none&#39;; browsing-topics &#39;none&#39;; camera &#39;none&#39;; ch-ua &#39;none&#39;; display-capture &#39;none&#39;; domain-agent &#39;none&#39;; document-domain &#39;none&#39;; encrypted-media &#39;none&#39;; execution-while-not-rendered &#39;none&#39;; execution-while-out-of-viewport &#39;none&#39;; gamepad &#39;none&#39;; geolocation &#39;none&#39;; gyroscope &#39;none&#39;; hid &#39;none&#39;; identity-credentials-get &#39;none&#39;; idle-detection &#39;none&#39;; keyboard-map &#39;none&#39;; local-fonts &#39;none&#39;; magnetometer &#39;none&#39;; microphone &#39;none&#39;; midi &#39;none&#39;; navigation-override &#39;none&#39;; otp-credentials &#39;none&#39;; payment &#39;none&#39;; picture-in-picture &#39;none&#39;; publickey-credentials-create &#39;none&#39;; publickey-credentials-get &#39;none&#39;; screen-wake-lock &#39;none&#39;; serial &#39;none&#39;; speaker-selection &#39;none&#39;; sync-xhr &#39;none&#39;; usb &#39;none&#39;; web-share &#39;none&#39;; window-management &#39;none&#39;; xr-spatial-tracking &#39;none&#39;&#34;
      style=&#34;border-width: 0;&#34;
      loading=&#34;lazy&#34;
      csp=&#34;sandbox allow-scripts allow-same-origin;&#34; src=&#34;https://www.youtube-nocookie.com/embed/bK00T2wEW_w&#34;&gt;
   &lt;/iframe&gt;
   &lt;br/&gt;
   &lt;br/&gt;
&lt;/div&gt;

&lt;p&gt;Here is a video showing a close up of the final parting off step:&lt;/p&gt;
&lt;div class=&#34;video-container&#34;&gt;
   &lt;iframe
      credentialless
      allowfullscreen
      sandbox=&#34;allow-scripts allow-same-origin&#34;
      allow=&#34;accelerometer &#39;none&#39;; ambient-light-sensor &#39;none&#39;; autoplay &#39;none&#39;; battery &#39;none&#39;; bluetooth &#39;none&#39;; browsing-topics &#39;none&#39;; camera &#39;none&#39;; ch-ua &#39;none&#39;; display-capture &#39;none&#39;; domain-agent &#39;none&#39;; document-domain &#39;none&#39;; encrypted-media &#39;none&#39;; execution-while-not-rendered &#39;none&#39;; execution-while-out-of-viewport &#39;none&#39;; gamepad &#39;none&#39;; geolocation &#39;none&#39;; gyroscope &#39;none&#39;; hid &#39;none&#39;; identity-credentials-get &#39;none&#39;; idle-detection &#39;none&#39;; keyboard-map &#39;none&#39;; local-fonts &#39;none&#39;; magnetometer &#39;none&#39;; microphone &#39;none&#39;; midi &#39;none&#39;; navigation-override &#39;none&#39;; otp-credentials &#39;none&#39;; payment &#39;none&#39;; picture-in-picture &#39;none&#39;; publickey-credentials-create &#39;none&#39;; publickey-credentials-get &#39;none&#39;; screen-wake-lock &#39;none&#39;; serial &#39;none&#39;; speaker-selection &#39;none&#39;; sync-xhr &#39;none&#39;; usb &#39;none&#39;; web-share &#39;none&#39;; window-management &#39;none&#39;; xr-spatial-tracking &#39;none&#39;&#34;
      style=&#34;border-width: 0;&#34;
      loading=&#34;lazy&#34;
      csp=&#34;sandbox allow-scripts allow-same-origin;&#34; src=&#34;https://www.youtube-nocookie.com/embed/_Q8DdQ0NQlQ&#34;&gt;
   &lt;/iframe&gt;
   &lt;br/&gt;
   &lt;br/&gt;
&lt;/div&gt;

&lt;p&gt;Closeups of the results (new on the left, original on the right):&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-real-project-on-the-pocket-nc/images/inner.jpg&#34; width=&#34;75%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-real-project-on-the-pocket-nc/images/outer.jpg&#34; width=&#34;75%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;And for those so inclined, here is a full length video of the operation from within the enclosure:&lt;/p&gt;
&lt;div class=&#34;video-container&#34;&gt;
   &lt;iframe
      credentialless
      allowfullscreen
      sandbox=&#34;allow-scripts allow-same-origin&#34;
      allow=&#34;accelerometer &#39;none&#39;; ambient-light-sensor &#39;none&#39;; autoplay &#39;none&#39;; battery &#39;none&#39;; bluetooth &#39;none&#39;; browsing-topics &#39;none&#39;; camera &#39;none&#39;; ch-ua &#39;none&#39;; display-capture &#39;none&#39;; domain-agent &#39;none&#39;; document-domain &#39;none&#39;; encrypted-media &#39;none&#39;; execution-while-not-rendered &#39;none&#39;; execution-while-out-of-viewport &#39;none&#39;; gamepad &#39;none&#39;; geolocation &#39;none&#39;; gyroscope &#39;none&#39;; hid &#39;none&#39;; identity-credentials-get &#39;none&#39;; idle-detection &#39;none&#39;; keyboard-map &#39;none&#39;; local-fonts &#39;none&#39;; magnetometer &#39;none&#39;; microphone &#39;none&#39;; midi &#39;none&#39;; navigation-override &#39;none&#39;; otp-credentials &#39;none&#39;; payment &#39;none&#39;; picture-in-picture &#39;none&#39;; publickey-credentials-create &#39;none&#39;; publickey-credentials-get &#39;none&#39;; screen-wake-lock &#39;none&#39;; serial &#39;none&#39;; speaker-selection &#39;none&#39;; sync-xhr &#39;none&#39;; usb &#39;none&#39;; web-share &#39;none&#39;; window-management &#39;none&#39;; xr-spatial-tracking &#39;none&#39;&#34;
      style=&#34;border-width: 0;&#34;
      loading=&#34;lazy&#34;
      csp=&#34;sandbox allow-scripts allow-same-origin;&#34; src=&#34;https://www.youtube-nocookie.com/embed/RvZ1_O5oE18&#34;&gt;
   &lt;/iframe&gt;
   &lt;br/&gt;
   &lt;br/&gt;
&lt;/div&gt;

&lt;p&gt;If you got past the glitchy, out of focus moments, awkward manual tool changes and endless B axis unwind,
you might have enjoyed the ability to simply snap off the workpiece as it was left with a minimal 0.1mm ring around
the central hole connecting it to the stock.&lt;/p&gt;
&lt;p&gt;As observed before, I think I need to upgrade the camera technology here to improve depth of field,
vibration handling and enclosure open/close remote control.&lt;/p&gt;
&lt;p&gt;I also really need to understand how to use the &lt;code&gt;M999&lt;/code&gt; GCode to avoid that painfully long B-Axis unwind at the end: &lt;a href=&#34;https://pentamachine.atlassian.net/wiki/spaces/KCUR/pages/1713471506/Rotary+Unwind&#34;&gt;https://pentamachine.atlassian.net/wiki/spaces/KCUR/pages/1713471506/Rotary+Unwind&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/cnc">cnc</category>
            <category domain="https://vectronic.io/tags/fusion360">fusion360</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Bun, WASM and Rust projects with GitHub Actions</title>
            <link>https://vectronic.io/posts/template-bun-wasm-and-rust-projects-with-github-actions/</link>
            <pubDate>Tue, 29 Jul 2025 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/template-bun-wasm-and-rust-projects-with-github-actions/</guid>
            <description>&lt;p&gt;Following on from a &lt;a href=&#34;https://vectronic.io/posts/migrate-to-deno&#34;&gt;previously outlined move to Deno&lt;/a&gt; I&amp;rsquo;ve now moved to &lt;a href=&#34;https://bun.com&#34;&gt;Bun&lt;/a&gt; 😅&lt;/p&gt;
&lt;p&gt;The main thing I moved &lt;strong&gt;to&lt;/strong&gt; Deno for was a nice way to acheive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A single executable binary via &lt;a href=&#34;https://deno.land/manual/tools/compiler&#34;&gt;Deno Compile&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Cross platform executables via &lt;a href=&#34;https://deno.land/manual/tools/compiler#cross-compilation&#34;&gt;cross-compilation support in Deno&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ability to dynamically load and run additional logic after installation via Deno&amp;rsquo;s support for the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import&#34;&gt;Javascript import() function&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After a while I discovered these items don&amp;rsquo;t all work well together. It came to light that dynamic loading of modules external to the compiled Deno application was not really supported: &lt;a href=&#34;https://github.com/denoland/deno/issues/18327&#34;&gt;https://github.com/denoland/deno/issues/18327&lt;/a&gt; Fair enough, everyone has their priorities&amp;hellip;&lt;/p&gt;
&lt;p&gt;I then read (but can&amp;rsquo;t remember where) that Bun &lt;strong&gt;does&lt;/strong&gt; support this. 🥳  Ok, game on!&lt;/p&gt;
&lt;p&gt;But (there is always a but&amp;hellip;) in Bun there is no support for loading from a remote URL: &lt;a href=&#34;https://github.com/oven-sh/bun/issues/38&#34;&gt;https://github.com/oven-sh/bun/issues/38&lt;/a&gt; Again, everyone has their priorities&amp;hellip; 😣&lt;/p&gt;
&lt;p&gt;So in Bun, dynamic imports can reference a local filesystem URL only. However, they CAN be loaded from a compiled executable and they can be loaded from absolute paths or paths relative to the compiled executable. To workaround lack of remote URL support, I wrote a little helper to pull remote modules locally:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/flowscripter/dynamic-plugin-framework/blob/main/src/plugin_manager/util/PluginLoader.ts#L26-L47&#34;&gt;https://github.com/flowscripter/dynamic-plugin-framework/blob/main/src/plugin_manager/util/PluginLoader.ts#L26-L47&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;after which I can import OK here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/flowscripter/dynamic-plugin-framework/blob/main/src/plugin_manager/util/PluginLoader.ts#L85&#34;&gt;https://github.com/flowscripter/dynamic-plugin-framework/blob/main/src/plugin_manager/util/PluginLoader.ts#L85&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So we&amp;rsquo;re good and I am still mostly sane!&lt;/p&gt;
&lt;p&gt;So, after previously presenting: &amp;ldquo;a set of template Deno, Rust and WASM projects on GitHub&amp;rdquo; in &lt;a href=&#34;https://vectronic.io/posts/template-deno-wasm-and-rust-projects-with-github-actions-ci&#34;&gt;this post&lt;/a&gt; I am now presenting:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;a set of &lt;a href=&#34;https://github.com/orgs/flowscripter/repositories?q=template&#34;&gt;template Bun, Rust and WASM projects on GitHub&lt;/a&gt;&amp;rdquo; together with GitHub &lt;a href=&#34;https://github.com/flowscripter/.github/tree/v1/actions&#34;&gt;Actions&lt;/a&gt;, &lt;a href=&#34;https://github.com/flowscripter/.github/tree/v1/.github/workflows&#34;&gt;Shared Workflows&lt;/a&gt; and &lt;a href=&#34;https://github.com/flowscripter/.github/tree/v1/workflow-templates&#34;&gt;Template Workflows&lt;/a&gt; for continuous integration.&lt;/p&gt;
&lt;p&gt;For my use cases I am looking to achieve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A scriptable high-level layer (Bun TypeScript) controlling a performant lower-level core (Rust).&lt;/li&gt;
&lt;li&gt;A single executable binary which can be cross-compiled.&lt;/li&gt;
&lt;li&gt;Ability for the executable to dynamically load and run additional logic after installation via the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import&#34;&gt;Javascript import() function&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Support for running as much as possible agnostically as an OS process or in a browser runtime with the ability to compile Rust to WASM.&lt;/li&gt;
&lt;li&gt;Simple project scaffolding via Bun&amp;rsquo;s all-in-one approach&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just on that last point&amp;hellip; turns out Bun doesn&amp;rsquo;t do linting or documentation generation &lt;a href=&#34;https://github.com/oven-sh/bun/issues/2246&#34;&gt;https://github.com/oven-sh/bun/issues/2246&lt;/a&gt; There we are with priorities again&amp;hellip; 😣 So for this I am actually still using Deno 🤪 as it &amp;ldquo;just works&amp;rdquo; (and seems to handle running on a Bun biased codebase):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;deno fmt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deno lint index.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deno doc --html index.ts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;
&lt;p&gt;Before getting into details, some of the feature highlights I&amp;rsquo;ve managed to achieve are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;a href=&#34;https://github.com/flowscripter/template-bun-executable/releases&#34;&gt;single executable&lt;/a&gt; available for Linux, MacOS (available via brew) and Windows (available via winget) with Rust FFI and dynamic import.&lt;/li&gt;
&lt;li&gt;Roughly the same functionality &lt;a href=&#34;https://flowscripter.github.io/template-bun-webapp/&#34;&gt;running in a browser&lt;/a&gt; with WASM (dynamic import not applicable here).&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://app.codecov.io/gh/flowscripter&#34;&gt;Instrumented test coverage analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Working example projects with GitHub actions for testing, compiling, versioning and releasing for:
&lt;ul&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;li&gt;Rust + Bun via FFI Bindings&lt;/li&gt;
&lt;li&gt;Rust + Bun via WASM&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Automated PRs, testing, merging, versioning and releasing for internal and 3rd party dependencies&lt;/li&gt;
&lt;li&gt;Automatically updated API documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;repositories&#34;&gt;Repositories&lt;/h2&gt;
&lt;p&gt;The GitHub repositories involved in this effort are as follows:&lt;/p&gt;
&lt;h3 id=&#34;application-projects&#34;&gt;&amp;ldquo;Application&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-bun-executable&#34;&gt;flowscripter/template-bun-executable&lt;/a&gt;: Project template for a Bun executable.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-bun-webapp&#34;&gt;flowscripter/template-bun-webapp&lt;/a&gt;: Project template for a Bun based webapp with Bun and Rust based WASM library dependencies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;simple-library-projects&#34;&gt;&amp;ldquo;Simple Library&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-bun-library&#34;&gt;flowscripter/template-bun-library&lt;/a&gt;: Project template for a Bun library.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-rust-library&#34;&gt;flowscripter/template-rust-library&lt;/a&gt;: Project template for a Rust library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;glue-library-projects&#34;&gt;&amp;ldquo;Glue Library&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-bun-rust-library&#34;&gt;flowscripter/template-bun-rust-library&lt;/a&gt;: Project template for a Rust library with Bun FFI bindings.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-bun-wasm-rust-library&#34;&gt;flowscripter/template-bun-wasm-rust-library&lt;/a&gt;: Project template for a Rust library compiled to WASM exposed as a Bun module.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ci-projects&#34;&gt;&amp;ldquo;CI&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/.github&#34;&gt;flowscripter/.github&lt;/a&gt;: GitHub Actions, Shared Workflows and Workflow Templates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a-picture-is-worth-a-1000-words-or-maybe-its-just-confusing&#34;&gt;A picture is worth a 1000 words&amp;hellip; or maybe its just confusing&amp;hellip;&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s big and complex, but I hope the following describes things visually. It shows the projects (together with their
artifacts and inter-dependencies).&lt;/p&gt;
&lt;p&gt;Click on it to open in a larger form.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/flowscripter-ci.svg&#34;&gt;
&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/template-bun-wasm-and-rust-projects-with-github-actions/images/flowscripter-ci.png&#34; alt=&#34;Flowscripter CI - click to enlarge&#34; width=&#34;50%&#34;/&gt; &lt;figcaption&gt;
    
    &lt;p&gt;
    Flowscripter CI - click to enlarge
    
    
    &lt;/p&gt;
    
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;feedback&#34;&gt;Feedback&lt;/h2&gt;
&lt;p&gt;If anyone is interested in this and has actually read this far, I would love some feedback on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;suggested improvements or recommendations&lt;/li&gt;
&lt;li&gt;any issues discovered&lt;/li&gt;
&lt;/ul&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/bun">bun</category>
            <category domain="https://vectronic.io/tags/wasm">wasm</category>
            <category domain="https://vectronic.io/tags/rust">rust</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Minitel Terminal Connected via Asterisk</title>
            <link>https://vectronic.io/posts/minitel-terminal-connected-via-asterisk/</link>
            <pubDate>Mon, 30 Dec 2024 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/minitel-terminal-connected-via-asterisk/</guid>
            <description>&lt;p&gt;I took some time during the holiday to get the Minitel I inherited from the parents-in-law connected to my home server.
As I already run Asterisk on the server and have analogue telephony hardware, I wanted to use the analogue dialup modem
rather than opting for the serial port available on some Minitel terminals.&lt;/p&gt;
&lt;p&gt;Overall the setup is:&lt;/p&gt;
&lt;p&gt;Analogue Phone + Minitel Terminal =&amp;gt; Grandstream ATA =&amp;gt; Asterisk =&amp;gt; &lt;a href=&#34;https://github.com/johnnewcombe/asterisk-Softmodem&#34;&gt;SoftModem&lt;/a&gt; =&amp;gt; Python &lt;a href=&#34;https://github.com/BwanaFr/minitel-server&#34;&gt;Minitel Server&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is a video showing initial connection and navigating to some adult content of the era:&lt;/p&gt;
&lt;div class=&#34;video-container&#34;&gt;
   &lt;iframe
      credentialless
      allowfullscreen
      sandbox=&#34;allow-scripts allow-same-origin&#34;
      allow=&#34;accelerometer &#39;none&#39;; ambient-light-sensor &#39;none&#39;; autoplay &#39;none&#39;; battery &#39;none&#39;; bluetooth &#39;none&#39;; browsing-topics &#39;none&#39;; camera &#39;none&#39;; ch-ua &#39;none&#39;; display-capture &#39;none&#39;; domain-agent &#39;none&#39;; document-domain &#39;none&#39;; encrypted-media &#39;none&#39;; execution-while-not-rendered &#39;none&#39;; execution-while-out-of-viewport &#39;none&#39;; gamepad &#39;none&#39;; geolocation &#39;none&#39;; gyroscope &#39;none&#39;; hid &#39;none&#39;; identity-credentials-get &#39;none&#39;; idle-detection &#39;none&#39;; keyboard-map &#39;none&#39;; local-fonts &#39;none&#39;; magnetometer &#39;none&#39;; microphone &#39;none&#39;; midi &#39;none&#39;; navigation-override &#39;none&#39;; otp-credentials &#39;none&#39;; payment &#39;none&#39;; picture-in-picture &#39;none&#39;; publickey-credentials-create &#39;none&#39;; publickey-credentials-get &#39;none&#39;; screen-wake-lock &#39;none&#39;; serial &#39;none&#39;; speaker-selection &#39;none&#39;; sync-xhr &#39;none&#39;; usb &#39;none&#39;; web-share &#39;none&#39;; window-management &#39;none&#39;; xr-spatial-tracking &#39;none&#39;&#34;
      style=&#34;border-width: 0;&#34;
      loading=&#34;lazy&#34;
      csp=&#34;sandbox allow-scripts allow-same-origin;&#34; src=&#34;https://www.youtube-nocookie.com/embed/cCO2UKCH4wk&#34;&gt;
   &lt;/iframe&gt;
   &lt;br/&gt;
   &lt;br/&gt;
&lt;/div&gt;

&lt;p&gt;Apart from soldering some raw wires onto the French phone plug, the Minitel terminal remains unmodified:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/minitel-terminal-connected-via-asterisk/images/connector.jpg&#34; width=&#34;30%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Most of the work to get this up and running was covered in this excellent blog entry: &lt;a href=&#34;https://glasstty.com/building-a-standalone-softmodem-enabled-pabx/&#34;&gt;Building a Standalone Softmodem Enabled PABX
&lt;/a&gt; 🙏&lt;/p&gt;
&lt;p&gt;Things went quite smoothly until I got stuck with garbled text on the screen when connecting to the Minitel server. After checking
the analogue side of things (and also successfully connecting to the Telstar service hosted at &lt;a href=&#34;https://glasstty.com&#34;&gt;https://glasstty.com&lt;/a&gt;) I started to suspect
byte processing logic in the Python Minitel server&amp;hellip;&lt;/p&gt;
&lt;p&gt;Indeed, the issue turned out to be that the Minitel server had been developed to work with the original version of the Softmodem code which does not perform
parity processing. Hence the Minitel server was performing this. As I was using a more up to date fork of the Softmodem, it was already performing the parity processing: &lt;a href=&#34;https://github.com/johnnewcombe/asterisk-Softmodem&#34;&gt;https://github.com/johnnewcombe/asterisk-Softmodem&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I created a fork of the Minitel server allowing parity processing to be disabled: &lt;a href=&#34;https://github.com/vectronic/minitel-server&#34;&gt;https://github.com/vectronic/minitel-server&lt;/a&gt;
With this patch in place I was able to get it all working on FreeBSD with Asterisk 18. 🥳&lt;/p&gt;
&lt;p&gt;Now I need to find an idea of what to connect this thing to rather than just local test and demo services&amp;hellip;.🤔&lt;/p&gt;
&lt;h3 id=&#34;further-details-and-notes&#34;&gt;Further Details and Notes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;UPDATE: April 4th 2026&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is now a Docker image of this available: &lt;code&gt;vectronic/asterisk-minitel&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;See source and instructions at: &lt;a href=&#34;https://github.com/vectronic/asterisk-minitel-docker&#34;&gt;https://github.com/vectronic/asterisk-minitel-docker&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is build on Linux instead of Ubuntu thus avoiding patches below and the PR for &lt;code&gt;minitel-server&lt;/code&gt; has been merged upstream
so all in all things are a lot simpler.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Asterisk 18 and Softmodem Installation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In a FreeBSD jail:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pkg update &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; pkg upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pkg install git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone --depth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; https://git.FreeBSD.org/ports.git /usr/ports
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Edit &lt;code&gt;/usr/ports/Templates/config.site&lt;/code&gt; and change &lt;code&gt;${ac_cv_header_byteswap_h=yes}&lt;/code&gt; to &lt;code&gt;no&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setenv ALLOW_UNSUPPORTED_SYSTEM &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /usr/ports/net/asterisk18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl https://raw.githubusercontent.com/johnnewcombe/asterisk-Softmodem/app_softmodem/app_softmodem.c &amp;gt; /usr/ports/net/asterisk18/work/asterisk-18.25.0/apps/app_softmodem.c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Edit &lt;code&gt;/usr/ports/net/asterisk18/work/asterisk-18.25.0/apps/app_softmodem.c&lt;/code&gt; and add at the top:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define TRUE 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define FALSE 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /usr/ports/net/asterisk18/work/asterisk-18.25.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make menuselect
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /usr/ports/net/asterisk18/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make deinstall 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pw groupmod -n asterisk -g &lt;span style=&#34;color:#ae81ff&#34;&gt;1001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pw group mod asterisk -m asterisk
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown -R asterisk:asterisk /usr/local/etc/asterisk/ /usr/local/lib/asterisk /usr/local/share/asterisk
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod &lt;span style=&#34;color:#ae81ff&#34;&gt;644&lt;/span&gt; /usr/local/etc/asterisk/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Asterisk Configuration Files&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@asterisk:~ &lt;span style=&#34;color:#75715e&#34;&gt;# cat /usr/local/etc/asterisk/pjsip.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;transport-udp&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;transport
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;protocol&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;udp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bind&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;192.168.22.22
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;6000&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;endpoint
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;context&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;foo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;disallow&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;allow&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;ulaw
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;transport&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;transport-udp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;auth&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;commonauth
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aors&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;6000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;commonauth&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;auth
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;auth_type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;userpass
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;username&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;password&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;6000&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;aor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;max_contacts&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@asterisk:~ &lt;span style=&#34;color:#75715e&#34;&gt;# cat /usr/local/etc/asterisk/extensions.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;foo&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 1,1,Dial&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;PJSIP/6000,20&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3610,1,Answer&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3610,n,Softmodem&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;127.0.0.1,3610,v&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;V23&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;ld&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;7&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;e&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3610,n,Hangup&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3611,1,Answer&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3611,n,Softmodem&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;127.0.0.1,3611,v&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;V23&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;ld&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;7&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;e&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3611,n,Hangup&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3614,1,Answer&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3614,n,Softmodem&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;127.0.0.1,3614,v&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;V23&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;ld&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;7&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;e&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3614,n,Hangup&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3615,1,Answer&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3615,n,Softmodem&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;127.0.0.1,3615,v&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;V23&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;ld&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;7&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;e&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exten &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; 3615,n,Hangup&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Minitel Server Setup&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone --depth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; https://github.com/vectronic/minitel-server.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Edit &lt;code&gt;minitel-server/constant.py&lt;/code&gt; and change &lt;code&gt;PROCESS_PARITY&lt;/code&gt; from &lt;code&gt;True&lt;/code&gt; to &lt;code&gt;False&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Setup the server to run on boot (I know, I know, this needs to be changed to a non-root user):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@asterisk:~ &lt;span style=&#34;color:#75715e&#34;&gt;# cat /usr/local/etc/rc.d/minitel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# PROVIDE: minitel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# REQUIRE: LOGIN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# KEYWORD: shutdown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. /etc/rc.subr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;minitel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rcvar&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;minitel_enable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;load_rc_config $name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;minitel_enable=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NO&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;minitel_home_dir:=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/root/minitel-server&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pidfile&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/var/run/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;name&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;command&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/usr/sbin/daemon
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;command_args&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-f -P &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;pidfile&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; -u root /bin/sh -c &amp;#39;cd /root/minitel-server &amp;amp;&amp;amp; /usr/local/bin/python3.11 MinitelSrv.py&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run_rc_command &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$1&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Start Services&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysrc asterisk_enable&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;YES&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysrc minitel_enable&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;YES&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service asterisk start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service minitel start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/nostalgia">nostalgia</category>
            <category domain="https://vectronic.io/tags/hardware">hardware</category>
            <category domain="https://vectronic.io/tags/python">python</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Beginner Chips</title>
            <link>https://vectronic.io/posts/beginner-chips/</link>
            <pubDate>Thu, 21 Nov 2024 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/beginner-chips/</guid>
            <description>&lt;p&gt;A second attempt at the tutorial from Penta was reasonably successful.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/beginner-chips/images/beginner-chips.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;The first attempt was most definitely not: the collet I used didn&amp;rsquo;t tighten up on the workpiece enough
and the workpiece moved towards the mill during the operation. As I looked on in awe at the increasing size of the chips without thinking
to intervene, the mill eventually plunged into the workpiece which then moved and snapped the mill. I have video but won&amp;rsquo;t
publish that&amp;hellip; As I said: not successful, beginner chips 🥹&lt;/p&gt;
&lt;p&gt;This second attempt was reasonably successful excepting a G-code error near the end of the run. I believe it was because
the tool length did not provide enough clearance for parting off, although I am sure I ran the simulation first&amp;hellip;
Hence a third attempt  is in order to double check that everything works as expected and I am doing what is expected of me!&lt;/p&gt;
&lt;p&gt;Here is a video showing some of the key action:&lt;/p&gt;
&lt;div class=&#34;video-container&#34;&gt;
   &lt;iframe
      credentialless
      allowfullscreen
      sandbox=&#34;allow-scripts allow-same-origin&#34;
      allow=&#34;accelerometer &#39;none&#39;; ambient-light-sensor &#39;none&#39;; autoplay &#39;none&#39;; battery &#39;none&#39;; bluetooth &#39;none&#39;; browsing-topics &#39;none&#39;; camera &#39;none&#39;; ch-ua &#39;none&#39;; display-capture &#39;none&#39;; domain-agent &#39;none&#39;; document-domain &#39;none&#39;; encrypted-media &#39;none&#39;; execution-while-not-rendered &#39;none&#39;; execution-while-out-of-viewport &#39;none&#39;; gamepad &#39;none&#39;; geolocation &#39;none&#39;; gyroscope &#39;none&#39;; hid &#39;none&#39;; identity-credentials-get &#39;none&#39;; idle-detection &#39;none&#39;; keyboard-map &#39;none&#39;; local-fonts &#39;none&#39;; magnetometer &#39;none&#39;; microphone &#39;none&#39;; midi &#39;none&#39;; navigation-override &#39;none&#39;; otp-credentials &#39;none&#39;; payment &#39;none&#39;; picture-in-picture &#39;none&#39;; publickey-credentials-create &#39;none&#39;; publickey-credentials-get &#39;none&#39;; screen-wake-lock &#39;none&#39;; serial &#39;none&#39;; speaker-selection &#39;none&#39;; sync-xhr &#39;none&#39;; usb &#39;none&#39;; web-share &#39;none&#39;; window-management &#39;none&#39;; xr-spatial-tracking &#39;none&#39;&#34;
      style=&#34;border-width: 0;&#34;
      loading=&#34;lazy&#34;
      csp=&#34;sandbox allow-scripts allow-same-origin;&#34; src=&#34;https://www.youtube-nocookie.com/embed/HnZFxEzFJRg&#34;&gt;
   &lt;/iframe&gt;
   &lt;br/&gt;
   &lt;br/&gt;
&lt;/div&gt;

&lt;p&gt;At some point I will need to upgrade from the old iPhone in use for filming as I&amp;rsquo;m not happy with the quality of the video.&lt;/p&gt;
&lt;p&gt;Next steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;third attempt at the tutorial&lt;/li&gt;
&lt;li&gt;probably a second run at the sample cube piece tutorial now that I am setup in the enclosure with video recording&lt;/li&gt;
&lt;li&gt;integration of the &lt;a href=&#34;https://vers.ge/en/blog/user-guides/wlr-v8&#34;&gt;Vers Wireless Touch Probe&lt;/a&gt; which seems to have had some &lt;a href=&#34;https://community.pentamachine.com/t/using-josh-pieper-probe-with-fusion-360/453/23&#34;&gt;further activity&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/cnc">cnc</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Pocket NC Enclosure Reality</title>
            <link>https://vectronic.io/posts/pocket-nc-enclosure-reality/</link>
            <pubDate>Sat, 14 Sep 2024 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/pocket-nc-enclosure-reality/</guid>
            <description>&lt;p&gt;Over a long duration I finally constructed the Pocket NC enclosure. And now after an even longer period of time I am posting about it.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-reality/images/front.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(reasonably) soft close/open with gas struts&lt;/li&gt;
&lt;li&gt;high visibility with clear perspex on four sides&lt;/li&gt;
&lt;li&gt;elevated mounting of Pocket NC to allow longer stock in the ER40 collet&lt;/li&gt;
&lt;li&gt;enclosure open signal integration with Pocket NC&lt;/li&gt;
&lt;li&gt;internal iPhone mount for video recording of CNC sessions 🤓&lt;/li&gt;
&lt;li&gt;integrated LED lighting&lt;/li&gt;
&lt;li&gt;lighting partially switches off when opening to avoid blinding the user 😎&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The build pretty much worked out as planned. There was only one main &amp;ldquo;gotcha&amp;rdquo; which was that the
gas struts exert a significant amount of force
on the frame resulting in a large degree of shaking when opening the enclosure.
For this reason I needed to add some unplanned bracing plates on the rear side uprights.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-reality/images/bracing.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;The rear of the enclosure provides space for mounting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a power board&lt;/li&gt;
&lt;li&gt;LED lighting power supply&lt;/li&gt;
&lt;li&gt;a network switch&lt;/li&gt;
&lt;li&gt;a POE lightning cable to power and connect an internally mounted iPhone for recording CNC sessions&lt;/li&gt;
&lt;li&gt;a POE lightning cable to power and connect an externally located iPad for the Penta interface&lt;/li&gt;
&lt;li&gt;the receiver for a &lt;a href=&#34;https://vers.ge/en/blog/user-guides/wlr-v8&#34;&gt;Vers Wireless Touch Probe&lt;/a&gt; - integration of this is the next step on the journey&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-reality/images/rear.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;I also worked on a small fitting to allow a dial gauge to be attached. I was planning to measure repeatability, but I&amp;rsquo;m not sure how useful this will be in practice given it is mounted on a movable part of the machine&amp;hellip;&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-reality/images/dial_gauge.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;It all looks pretty cool with the iPad beside it for convenient control:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-reality/images/ipad.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Here is a video showing some of the details:&lt;/p&gt;
&lt;div class=&#34;video-container&#34;&gt;
   &lt;iframe
      credentialless
      allowfullscreen
      sandbox=&#34;allow-scripts allow-same-origin&#34;
      allow=&#34;accelerometer &#39;none&#39;; ambient-light-sensor &#39;none&#39;; autoplay &#39;none&#39;; battery &#39;none&#39;; bluetooth &#39;none&#39;; browsing-topics &#39;none&#39;; camera &#39;none&#39;; ch-ua &#39;none&#39;; display-capture &#39;none&#39;; domain-agent &#39;none&#39;; document-domain &#39;none&#39;; encrypted-media &#39;none&#39;; execution-while-not-rendered &#39;none&#39;; execution-while-out-of-viewport &#39;none&#39;; gamepad &#39;none&#39;; geolocation &#39;none&#39;; gyroscope &#39;none&#39;; hid &#39;none&#39;; identity-credentials-get &#39;none&#39;; idle-detection &#39;none&#39;; keyboard-map &#39;none&#39;; local-fonts &#39;none&#39;; magnetometer &#39;none&#39;; microphone &#39;none&#39;; midi &#39;none&#39;; navigation-override &#39;none&#39;; otp-credentials &#39;none&#39;; payment &#39;none&#39;; picture-in-picture &#39;none&#39;; publickey-credentials-create &#39;none&#39;; publickey-credentials-get &#39;none&#39;; screen-wake-lock &#39;none&#39;; serial &#39;none&#39;; speaker-selection &#39;none&#39;; sync-xhr &#39;none&#39;; usb &#39;none&#39;; web-share &#39;none&#39;; window-management &#39;none&#39;; xr-spatial-tracking &#39;none&#39;&#34;
      style=&#34;border-width: 0;&#34;
      loading=&#34;lazy&#34;
      csp=&#34;sandbox allow-scripts allow-same-origin;&#34; src=&#34;https://www.youtube-nocookie.com/embed/NdqqZWR6SUQ&#34;&gt;
   &lt;/iframe&gt;
   &lt;br/&gt;
   &lt;br/&gt;
&lt;/div&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/cnc">cnc</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Pocket NC Enclosure Design</title>
            <link>https://vectronic.io/posts/pocket-nc-enclosure-design/</link>
            <pubDate>Tue, 03 Oct 2023 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/pocket-nc-enclosure-design/</guid>
            <description>&lt;p&gt;Before getting serious with the Pocket NC V2-50CHK, I want to build an enclosure for it. Although there is one
available to buy commercially, I wanted to build a custom one myself that has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;more vertical clearance underneath the B axis so that I can use longer stock in the ER-40 collet&lt;/li&gt;
&lt;li&gt;excellent access to the machine when open&lt;/li&gt;
&lt;li&gt;excellent visibility of the machine when closed&lt;/li&gt;
&lt;li&gt;built-in LED lighting&lt;/li&gt;
&lt;/ul&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-design/images/closed.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;I plan to make the enclosure using 80-20 style aluminium profile and fittings from &lt;a href=&#34;https://www.aluminium-profile.co.uk/aluminium-profile-components/br-range-compatible-with-bosch-rexroth-profile&#34;&gt;KJN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gas-struts will keep the lid up when in the open position:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-design/images/open.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Basic dimensions and a more detailed view at each of the sections:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-design/images/base.png&#34; width=&#34;75%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-design/images/mount.png&#34; width=&#34;75%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/pocket-nc-enclosure-design/images/lid.png&#34; width=&#34;75%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Here is a link to the Fusion 360 design: [enclosure](&lt;a href=&#34;https://a360.co/3LIx0KI&#34;&gt;https://a360.co/3LIx0KI&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/cnc">cnc</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>First Pocket NC chips!</title>
            <link>https://vectronic.io/posts/first-pocket-nc-chips/</link>
            <pubDate>Wed, 05 Jul 2023 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/first-pocket-nc-chips/</guid>
            <description>&lt;p&gt;The first chips have been produced on my new pride and joy, the Penta Machine&amp;rsquo;s Pocket NC V2-50CHK!&lt;/p&gt;
&lt;p&gt;Here is short video showing the chips flying when following the excellent &lt;a href=&#34;https://pentamachine.atlassian.net/wiki/spaces/PNFUR/pages/1727037445/V2+Series+First+Part+Tutorial+Kinetic+Control&#34;&gt;First Part Tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;video class=&#34;movie-shortcode&#34; preload=&#34;auto&#34; autoplay controls poster=&#34;images/pocket-nc.jpg&#34; width=&#34;50%&#34;&gt;
&lt;source src=&#34;movies/pocket-nc.mp4&#34; type=&#34;video/mp4&#34;/&gt;
There should have been a video here but your browser does not seem
to support it.
&lt;/video&gt;

&lt;p&gt;After many years being consumed by software I am now back straddling software and hardware ❤️&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/cnc">cnc</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Nostalgia - NetToaster</title>
            <link>https://vectronic.io/posts/nostalgia-nettoaster/</link>
            <pubDate>Tue, 03 Jan 2023 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/nostalgia-nettoaster/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve held onto the hard copy of my Electrical Engineering Thesis for around 25 years. It recently suffered water damage so I decided
it was time to immortalise it on the world wide web.&lt;/p&gt;
&lt;p&gt;I say &amp;lsquo;world wide web&amp;rsquo; in preference to modern terminology such as &amp;rsquo;net&amp;rsquo;, &amp;lsquo;web&amp;rsquo; etc. in homage to the title of the thesis:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A TOASTER WITH A WORLD WIDE WEB INTERFACE&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here is a photo of the &amp;lsquo;completed&amp;rsquo; project:&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/photo-overview.jpg&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/nostalgia-nettoaster/images/photo-overview.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;and a photo of the electronics board:&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/photo-board.jpg&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/nostalgia-nettoaster/images/photo-board.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;I say &amp;lsquo;completed&amp;rsquo; as I suffered a major setback about 6 weeks before the due date when I fried the ethernet controller chip.
The lead time was over 3 months and so I set myself on a new journey of implementing network connectivity over &lt;a href=&#34;https://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol&#34;&gt;SLIP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This ate into my development time and consequently I only managed to get to the point where I had a multi-tasking OS running two processes: one outputting &amp;lsquo;S&amp;rsquo; and one outputting &amp;lsquo;O&amp;rsquo; over serial. Get it&amp;hellip;? &lt;em&gt;SOS&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Still, designing and building a compute board to interface with the &lt;a href=&#34;https://en.wikipedia.org/wiki/SuperH&#34;&gt;Hitachi SH1&lt;/a&gt; processor
and porting &lt;a href=&#34;https://xinu.cs.purdue.edu&#34;&gt;XINU&lt;/a&gt; to run on it was not easy - and I&amp;rsquo;m still proud of my achievement to this day.&lt;/p&gt;
&lt;p&gt;Click on the cover for the full thesis:&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;files/thesis.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/nostalgia-nettoaster/images/cover.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;And click on the floppy for the code:&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;files/toast.zip&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/nostalgia-nettoaster/images/floppy.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/nostalgia">nostalgia</category>
            <category domain="https://vectronic.io/tags/embedded">embedded</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Nostalgia - Pogo Web Browser</title>
            <link>https://vectronic.io/posts/nostalgia-pogo/</link>
            <pubDate>Tue, 03 Jan 2023 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/nostalgia-pogo/</guid>
            <description>&lt;p&gt;More than 20 years ago, in the &amp;lsquo;dotcom&amp;rsquo; era, I worked for the web design agency Razorfish and managed to get involved
in a more exciting gig working for a hardware spin-off developing the &lt;a href=&#34;https://en.wikipedia.org/wiki/Pogo_Mobile_and_nVoy&#34;&gt;Pogo Mobile&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was responsible for the development of the embedded web browser that acted as the sole UI for the device.&lt;/p&gt;
&lt;p&gt;I came across this printout of a screenshot I took when the browser rendering started to take shape.&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/pogo-screenshot.png&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/nostalgia-pogo/images/pogo-screenshot.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/nostalgia">nostalgia</category>
            <category domain="https://vectronic.io/tags/embedded">embedded</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Fusion 360 Baby Steps</title>
            <link>https://vectronic.io/posts/fusion-360-baby-steps/</link>
            <pubDate>Mon, 26 Sep 2022 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/fusion-360-baby-steps/</guid>
            <description>&lt;p&gt;Life is all about incremental steps forward. And&amp;hellip; some steps backwards and sideways as well&amp;hellip;&lt;/p&gt;
&lt;p&gt;I switched from FreeCAD to Fusion 360 as I want to end up doing some 5 Axis CNC Machining. Currently FreeCAD support
for this is very&amp;hellip; far&amp;hellip; away&amp;hellip;&lt;/p&gt;
&lt;p&gt;So here are the results of applying the same learning process of modelling a brick in Fusion 360:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/fusion-360-baby-steps/images/brick_4x2_render_1.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;And here is the online model: &lt;a href=&#34;https://a360.co/3dLLBre&#34;&gt;https://a360.co/3dLLBre&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I still have problems with lighting and materials when rendering, but hey, it&amp;rsquo;s good enough. A bad render isn&amp;rsquo;t going
to cause the physical item to fail&amp;hellip;&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/fusion-360-baby-steps/images/brick_4x2_render_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Some nice technical drawings:&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_1.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/fusion-360-baby-steps/images/brick_4x2_1.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Not sure how the difference in templates crept in&amp;hellip;&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/fusion-360-baby-steps/images/brick_4x2_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;And assembly animation for the win &lt;code&gt;\(^ヮ^)/&lt;/code&gt;&lt;/p&gt;
&lt;video class=&#34;movie-shortcode&#34; preload=&#34;auto&#34; autoplay controls poster=&#34;images/brick_assembly_animation.jpg&#34; width=&#34;50%&#34;&gt;
&lt;source src=&#34;movies/brick_assembly_animation.mp4&#34; type=&#34;video/mp4&#34;/&gt;
There should have been a video here but your browser does not seem
to support it.
&lt;/video&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/fusion360">fusion360</category>
            <category domain="https://vectronic.io/tags/legify">legify</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Deno, WASM and Rust projects with GitHub Actions</title>
            <link>https://vectronic.io/posts/template-deno-wasm-and-rust-projects-with-github-actions-ci/</link>
            <pubDate>Tue, 05 Jul 2022 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/template-deno-wasm-and-rust-projects-with-github-actions-ci/</guid>
            <description>&lt;p&gt;Presenting a set of template Rust, WASM and Deno projects &lt;a href=&#34;https://github.com/orgs/flowscripter/repositories?q=template&#34;&gt;on GitHub&lt;/a&gt;
which make use of GitHub &lt;a href=&#34;https://github.com/flowscripter/.github/tree/v1/actions&#34;&gt;Actions&lt;/a&gt; and &lt;a href=&#34;https://github.com/flowscripter/.github/tree/v1/workflow-templates&#34;&gt;Workflows&lt;/a&gt; for continuous integration.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve &lt;a href=&#34;https://vectronic.io/posts/migrate-to-deno&#34;&gt;previously outlined&lt;/a&gt; my reasons for evaluating Rust and Deno. Using these technologies,
I am looking to achieve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A scriptable high-level layer (&lt;a href=&#34;https://deno.land/manual/tools/repl#read-eval-print-loop&#34;&gt;Deno REPL&lt;/a&gt;) controlling a performant lower-level core (Rust).&lt;/li&gt;
&lt;li&gt;A single executable binary via &lt;a href=&#34;https://deno.land/manual/tools/compiler&#34;&gt;Deno Compile&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Cross platform executables via cross-compilation support for &lt;a href=&#34;https://deno.land/manual/tools/compiler#cross-compilation&#34;&gt;Deno&lt;/a&gt; and &lt;a href=&#34;https://rust-lang.github.io/rustup/cross-compilation.html&#34;&gt;Rust&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ability to dynamically load and run additional logic after installation via Deno&amp;rsquo;s support for the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import&#34;&gt;Javascript import() function&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Agnostic support for running as an OS process or in a browser runtime via Deno&amp;rsquo;s &lt;a href=&#34;https://deno.land/manual/runtime/web_platform_apis&#34;&gt;web platform APIs&lt;/a&gt; and the ability to compile &lt;a href=&#34;https://rustwasm.github.io/docs/book/&#34;&gt;Rust to WASM&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Simple project scaffolding via Deno&amp;rsquo;s stated &lt;a href=&#34;https://deno.land/manual/introduction#goals&#34;&gt;goal&lt;/a&gt; to &lt;em&gt;&amp;ldquo;provide built-in tooling to improve developer experience&amp;rdquo;&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wanted to see if these could all be achieved using free SaaS tooling for continuous integration including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;code analysis&lt;/li&gt;
&lt;li&gt;automated dependency updates&lt;/li&gt;
&lt;li&gt;automated unit testing and integration/acceptance testing&lt;/li&gt;
&lt;li&gt;automated semantic releases&lt;/li&gt;
&lt;li&gt;automatically generated API documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I created the template projects and GitHub workflow and actions discussed here to see if the technologies could deliver on
their promises and thus achieve my aims.&lt;/p&gt;
&lt;p&gt;I should state that I defaulted to using GitHub simply because I have been using it for several years now.
Beyond recent FOSS concerns in the &lt;a href=&#34;https://sfconservancy.org/blog/2022/jun/30/give-up-github-launch/&#34;&gt;news&lt;/a&gt; I haven&amp;rsquo;t discovered any functional deficiencies which have caused me to look elsewhere.&lt;/p&gt;
&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;
&lt;p&gt;Before getting into details (and the inevitable pain points), some of the feature highlights I&amp;rsquo;ve managed to achieve are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;a href=&#34;https://github.com/flowscripter/template-deno-executable/releases&#34;&gt;single executable&lt;/a&gt; available for Linux, MacOS and Windows with the same functionality also &lt;a href=&#34;https://flowscripter.github.io/template-deno-webapp/&#34;&gt;running in a browser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://app.codecov.io/gh/flowscripter&#34;&gt;Instrumented test coverage analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Working example projects with GitHub actions for testing, compiling, versioning and releasing for:
&lt;ul&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;Deno&lt;/li&gt;
&lt;li&gt;Rust + Deno via FFI Bindings&lt;/li&gt;
&lt;li&gt;Rust + Deno via WASM&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Automated PRs, testing, merging, versioning and releasing for internal and 3rd party dependencies&lt;/li&gt;
&lt;li&gt;Automatically updated API documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;repositories&#34;&gt;Repositories&lt;/h2&gt;
&lt;p&gt;The GitHub repositories involved in this effort are as follows:&lt;/p&gt;
&lt;h3 id=&#34;application-projects&#34;&gt;&amp;ldquo;Application&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-deno-executable&#34;&gt;flowscripter/template-deno-executable&lt;/a&gt;: Project template for a Deno executable.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-deno-webapp&#34;&gt;flowscripter/template-deno-webapp&lt;/a&gt;: Project template for a Deno based webapp with Deno and Rust based WASM library dependencies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;simple-library-projects&#34;&gt;&amp;ldquo;Simple Library&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-deno-library&#34;&gt;flowscripter/template-deno-library&lt;/a&gt;: Project template for a Deno library.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-rust-library&#34;&gt;flowscripter/template-rust-library&lt;/a&gt;: Project template for a Rust library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;glue-library-projects&#34;&gt;&amp;ldquo;Glue Library&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-deno-rust-library&#34;&gt;flowscripter/template-deno-rust-library&lt;/a&gt;: Project template for a Rust library with Deno FFI bindings.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-wasm-rust-library&#34;&gt;flowscripter/template-wasm-rust-library&lt;/a&gt;: Project template for a Rust library compiled to WASM.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/template-deno-wasm-rust-library&#34;&gt;flowscripter/template-deno-wasm-rust-library&lt;/a&gt;: Project template for a Rust library compiled to WASM exposed as a Deno module.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ci-projects&#34;&gt;&amp;ldquo;CI&amp;rdquo; Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/flowscripter/.github&#34;&gt;flowscripter/.github&lt;/a&gt;: GitHub Actions and Workflow Templates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a-picture-is-worth-a-1000-words-or-maybe-its-just-confusing&#34;&gt;A picture is worth a 1000 words&amp;hellip; or maybe its just confusing&amp;hellip;&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s big and complex, but I hope the following describes things visually. It shows the projects (together with their
artifacts and inter-dependencies) and various good and bad things to note.&lt;/p&gt;
&lt;p&gt;Click on it to open in a larger form.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/flowscripter-ci.svg&#34;&gt;
&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/template-deno-wasm-and-rust-projects-with-github-actions-ci/images/flowscripter-ci.png&#34; alt=&#34;Flowscripter CI - click to enlarge&#34; width=&#34;50%&#34;/&gt; &lt;figcaption&gt;
    
    &lt;p&gt;
    Flowscripter CI - click to enlarge
    
    
    &lt;/p&gt;
    
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;eclectic-mix-of-workarounds&#34;&gt;Eclectic Mix of Workarounds&lt;/h2&gt;
&lt;p&gt;Beyond some outstanding issues outlined further below, there were a few things I discovered which are worth noting:&lt;/p&gt;
&lt;h3 id=&#34;github-v1-branch&#34;&gt;.github v1 branch&lt;/h3&gt;
&lt;p&gt;As far as I am aware, the best approach to managing versioning of GitHub Actions in your own &lt;code&gt;.github&lt;/code&gt; repository without publishing them
is to use branches for versioning.&lt;/p&gt;
&lt;p&gt;Each time I push a new commit to &lt;a href=&#34;https://github.com/flowscripter/.github&#34;&gt;flowscripter/.github&lt;/a&gt; which involves an Action fix, I re-create the branch &lt;code&gt;v1&lt;/code&gt; on the &lt;code&gt;.github&lt;/code&gt; repository so that the updated Action implementation will be used by dependent repositories.&lt;/p&gt;
&lt;p&gt;As an example, the reference to the Action &lt;code&gt;release_deno_library&lt;/code&gt; in the &lt;a href=&#34;https://github.com/flowscripter/template-deno-library/blob/main/.github/workflows/release-deno-library.yml#L20&#34;&gt;template-deno-library&lt;/a&gt; project is:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flowscripter/.github/actions/release-deno-library@v1&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;github-pages-to-host-wasm-library-releases&#34;&gt;GitHub Pages to host WASM library releases&lt;/h3&gt;
&lt;p&gt;I used GitHub Pages to host a demo of the webapp.&lt;/p&gt;
&lt;p&gt;I also ended up using it as a poor-man&amp;rsquo;s &amp;ldquo;artifact repository&amp;rdquo; for hosting pure Javascript Modules which include WASM files. I tried solutions like &lt;a href=&#34;https://esm.sh&#34;&gt;esm.sh&lt;/a&gt; and
&lt;a href=&#34;https://unpkg.com&#34;&gt;unpkg.com&lt;/a&gt; however:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;These require opting back into the NodeJS+NPM package ecosystem (something I was trying to opt OUT OF by using Deno)&lt;/li&gt;
&lt;li&gt;It seemed there was nothing available which supported serving WASM files with the mime-type expected by Deno when it fetches WASM files within the modules created with &lt;a href=&#34;https://github.com/rustwasm/wasm-pack&#34;&gt;wasm-pack&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;reliance-on-node-and-npm&#34;&gt;Reliance on Node and NPM&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&#34;https://semantic-release.gitbook.io/semantic-release/&#34;&gt;semantic-release&lt;/a&gt; project is excellent.
However it is written using Node and NPM. I&amp;rsquo;d love to find GitHub Actions which fully wrap this functionality or a
single executable which doesn&amp;rsquo;t require an &lt;code&gt;npm install&lt;/code&gt; which kind of goes against the grain when trying to migrate to Deno&amp;hellip;&lt;/p&gt;
&lt;p&gt;Following on from this, the semantic release plugin &lt;a href=&#34;https://github.com/qiwi/semantic-release-gh-pages-plugin&#34;&gt;@qiwi/semantic-release-gh-pages-plugin&lt;/a&gt; expects the project being released to be
Node based and therefore expects a &lt;code&gt;package.json&lt;/code&gt; file to exist in the repository.
Therefore, as part of releasing a WASM compiled library to GitHub pages, I need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;perform an &lt;code&gt;npm install&lt;/code&gt; so that the &lt;code&gt;@qiwi/semantic-release-gh-pages-plugin&lt;/code&gt; works&lt;/li&gt;
&lt;li&gt;remove the generated &lt;code&gt;package.json&lt;/code&gt; BEFORE the &lt;a href=&#34;https://github.com/kettleby/semantic-release-rust&#34;&gt;semantic-release-rust&lt;/a&gt; tool is used to perform a Cargo publish (Cargo doesn&amp;rsquo;t like files which aren&amp;rsquo;t in Git when publishing).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The fact that this is a workaround for publishing to GitHub Pages which is in itself a workaround for hosting WASM library releases really does bite&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;git-update-of-main-branch&#34;&gt;Git Update of Main Branch&lt;/h3&gt;
&lt;p&gt;I wanted to apply branch permissions for ALL users, including administrators of the repositories.&lt;/p&gt;
&lt;p&gt;However, for Rust based repositories, the release number needs to be set in the &lt;code&gt;cargo.toml&lt;/code&gt; file when performing the release from the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;To achieve this, I needed the GitHub Action to be able to push directly to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;Thus I needed a Personal Access Token which will &lt;strong&gt;only&lt;/strong&gt; work if administrators (i.e. myself) ARE NOT included in branch permissions&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;bleeding-edge&#34;&gt;Bleeding Edge&lt;/h3&gt;
&lt;p&gt;Whilst writing this blog entry, the Actions making use of &lt;a href=&#34;https://github.com/denoland/deno_bindgen&#34;&gt;deno_bindgen&lt;/a&gt; stopped working due to this issue:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/denoland/deno_bindgen/issues/80&#34;&gt;https://github.com/denoland/deno_bindgen/issues/80&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you play with unstable APIs you&amp;rsquo;re gonna get hurt&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;outstanding-issues&#34;&gt;Outstanding Issues&lt;/h2&gt;
&lt;p&gt;The items I discovered which are blockers for my stated aims are as follows:&lt;/p&gt;
&lt;h3 id=&#34;dynamic-import-of-wasm-based-javascript-modules&#34;&gt;Dynamic Import of WASM based Javascript Modules&lt;/h3&gt;
&lt;p&gt;As far as I can tell, I can&amp;rsquo;t use dynamic imports (i.e. the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import&#34;&gt;Javascript import() function&lt;/a&gt;) with WASM based Javascript Modules
until this is implemented: &lt;a href=&#34;https://github.com/denoland/deno/issues/2552&#34;&gt;https://github.com/denoland/deno/issues/2552&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;deno-compile-support-for-dynamic-imports&#34;&gt;Deno Compile support for dynamic imports&lt;/h3&gt;
&lt;p&gt;Deno supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;compilation to a single binary executable &lt;code&gt;\(^ヮ^)/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dynamic imports i.e. the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import&#34;&gt;Javascript import() function&lt;/a&gt; &lt;code&gt;\(^ヮ^)/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However it doesn&amp;rsquo;t support both of these at the same time: &lt;a href=&#34;https://github.com/denoland/deno/issues/8655&#34;&gt;https://github.com/denoland/deno/issues/8655&lt;/a&gt; &lt;code&gt;(&amp;gt;_&amp;lt;)&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;deno_bindgen-updated-to-support-the-latest-unstable-deno-api&#34;&gt;deno_bindgen updated to support the latest unstable Deno API&lt;/h3&gt;
&lt;p&gt;I mentioned this earlier as a downside to being on the bleeding edge: &lt;a href=&#34;https://github.com/denoland/deno_bindgen/issues/80&#34;&gt;https://github.com/denoland/deno_bindgen/issues/80&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;automatic-rust-api-docs-for-projects-using-deno_bindgen&#34;&gt;Automatic Rust API docs for projects using &lt;code&gt;deno_bindgen&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Glue technologies like &lt;a href=&#34;https://github.com/denoland/deno_bindgen/issues/72&#34;&gt;deno_bindgen&lt;/a&gt; are excellent, however I seem to be &amp;lsquo;stuck&amp;rsquo; with this: &lt;a href=&#34;https://github.com/denoland/deno_bindgen/issues/72&#34;&gt;https://github.com/denoland/deno_bindgen/issues/72&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Without a change here, my automatically generated docs at &lt;a href=&#34;https://docs.rs&#34;&gt;https://docs.rs&lt;/a&gt; will continue to throw a &lt;a href=&#34;https://docs.rs/crate/flowscripter_template_deno_rust_library/1.0.6/builds/556217&#34;&gt;massive error&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;deno-signing-and-notarisation-support&#34;&gt;Deno signing and notarisation support&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s not great delivering a single binary executable if the OS is reticent to run it&amp;hellip; &lt;a href=&#34;https://github.com/denoland/deno/issues/11154&#34;&gt;https://github.com/denoland/deno/issues/11154&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;github-actions-support-for-apple-silicon&#34;&gt;GitHub Actions support for Apple Silicon&lt;/h3&gt;
&lt;p&gt;Not major, but until this is available I can&amp;rsquo;t fully implement cross-platform CI: &lt;a href=&#34;https://github.com/actions/virtual-environments/issues/2187&#34;&gt;https://github.com/actions/virtual-environments/issues/2187&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;feedback&#34;&gt;Feedback&lt;/h2&gt;
&lt;p&gt;If anyone is interested in this and has actually read this far, I would love some feedback on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;suggested improvements or recommendations&lt;/li&gt;
&lt;li&gt;any issues discovered&lt;/li&gt;
&lt;/ul&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/deno">deno</category>
            <category domain="https://vectronic.io/tags/wasm">wasm</category>
            <category domain="https://vectronic.io/tags/rust">rust</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Legify 0.4.0</title>
            <link>https://vectronic.io/posts/legify-0.4.0/</link>
            <pubDate>Mon, 21 Feb 2022 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/legify-0.4.0/</guid>
            <description>&lt;p&gt;A new feature release version of Legify is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.4.0&#34;&gt;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.4.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This provides a new &lt;code&gt;legify-technic-pin&lt;/code&gt; macro which renders a technic pin onto an existing Part Design workbench body.&lt;/p&gt;
&lt;p&gt;Therefore the &amp;ldquo;s&amp;rdquo; in the name of the project &amp;ldquo;freecad-legify-macros&amp;rdquo; now has real meaning! 😜&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/release">release</category>
            <category domain="https://vectronic.io/tags/freecad">freecad</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>3D Printed Brick Assemblies</title>
            <link>https://vectronic.io/posts/3d-printed-brick-assemblies/</link>
            <pubDate>Mon, 17 Jan 2022 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/3d-printed-brick-assemblies/</guid>
            <description>&lt;p&gt;I ordered some 3D prints of bricks designed with the legify macro code available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Presented below are two assemblies as rendered within FreeCAD and assembled in real life.&lt;/p&gt;
&lt;p&gt;Playing around with the physical prints it is obvious that they don&amp;rsquo;t &amp;lsquo;stick&amp;rsquo; together anywhere near as well as the real thing.&lt;/p&gt;
&lt;p&gt;Taking various measurements it seems that the quoted print accuracy of ±0.3% (min: ±0.15mm) really does come into play.
Given the &lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros/blob/master/Legify/Common.py#L23-L73&#34;&gt;various dimensions used in the models&lt;/a&gt;
it is obvious that a minimum error of 0.15mm will have a significant impact on some of the features.&lt;/p&gt;
&lt;p&gt;It looks like I will need to start exploring CNC machining sooner than expected if I want to achieve accuracy around ±0.05mm.&lt;/p&gt;
&lt;p&gt;I might also need a better setup for macro photography!&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_assembly_1_render.png&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/3d-printed-brick-assemblies/images/brick_assembly_1_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_assembly_1_3d_print.jpg&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/3d-printed-brick-assemblies/images/brick_assembly_1_3d_print.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_assembly_2_render.png&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/3d-printed-brick-assemblies/images/brick_assembly_2_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_assembly_2_3d_print.jpg&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/3d-printed-brick-assemblies/images/brick_assembly_2_3d_print.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/hardware">hardware</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Legify 0.3.0</title>
            <link>https://vectronic.io/posts/legify-0.3.0/</link>
            <pubDate>Wed, 17 Nov 2021 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/legify-0.3.0/</guid>
            <description>&lt;p&gt;A new feature release version of Legify is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.3.0&#34;&gt;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.3.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Beyond a number of measurement improvements, rendering of technic pins is now implemented.&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_2x1_front_pin_render.png&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.3.0/images/brick_2x1_front_pin_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;The latest macro code, brief overview and instructions are available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Be aware that due to this &lt;a href=&#34;https://tracker.freecad.org/view.php?id=4781&#34;&gt;bug in FreeCAD&lt;/a&gt; discovered while implementing technic pin support,
multiple technic pins will not render correctly at the moment.&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_2x1_front_pin_1_of_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.3.0/images/brick_2x1_front_pin_1_of_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_2x1_front_pin_2_of_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.3.0/images/brick_2x1_front_pin_2_of_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_1_of_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.3.0/images/brick_4x2_1_of_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_2_of_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.3.0/images/brick_4x2_2_of_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/release">release</category>
            <category domain="https://vectronic.io/tags/freecad">freecad</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>New FreeCAD Assembly Render and Animation</title>
            <link>https://vectronic.io/posts/new-freecad-assembly-render-and-animation/</link>
            <pubDate>Thu, 21 Oct 2021 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/new-freecad-assembly-render-and-animation/</guid>
            <description>&lt;p&gt;I have just completed the finishing touches on Technic pin support:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/new-freecad-assembly-render-and-animation/images/brick_assembly_2_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;There were a few potholes encountered on the journey and as always, they were solved with excellent community support:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?f=22&amp;amp;t=61597&#34;&gt;Behaviour of Object.Tip with PartDesign LinearPattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/FreeCAD/FreeCAD-render/issues/151&#34;&gt;Particular Assembly4 model fails to render correctly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I now have pins available in my assemblies, I was able to try out the animation support within the
&lt;a href=&#34;https://github.com/Zolko-123/FreeCAD_Assembly4&#34;&gt;Assembly4 Workbench&lt;/a&gt;:&lt;/p&gt;
&lt;video class=&#34;movie-shortcode&#34; preload=&#34;auto&#34; autoplay controls poster=&#34;images/brick_assembly_2_animation.jpg&#34; width=&#34;50%&#34;&gt;
&lt;source src=&#34;movies/brick_assembly_2_animation.mp4&#34; type=&#34;video/mp4&#34;/&gt;
There should have been a video here but your browser does not seem
to support it.
&lt;/video&gt;

&lt;p&gt;I will be pushing the Technic pins support and various improvements in the next couple of days to:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/legify">legify</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Recent FreeCAD Macro Lessons</title>
            <link>https://vectronic.io/posts/recent-freecad-macro-lessons/</link>
            <pubDate>Tue, 31 Aug 2021 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/recent-freecad-macro-lessons/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been developing a &lt;a href=&#34;https://www.freecadweb.org&#34;&gt;FreeCAD&lt;/a&gt; macro for a while which uses the PartDesign workbench:
&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m just wrapping up support for rendering technic pins (work in progress screenshot below) and this effort has led me to a few more nuggets of information
relating to PartDesign and Python scripting in FreeCAD.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/recent-freecad-macro-lessons/images/technic-pin-wip.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;h2 id=&#34;additive-pipe-with-path-and-profile-sketches&#34;&gt;Additive Pipe With Path and Profile Sketches&lt;/h2&gt;
&lt;p&gt;Developing the flange on the pin seen below introduced me to &lt;em&gt;AdditivePipe&lt;/em&gt; and the fact that &lt;em&gt;two&lt;/em&gt; sketches were required for a single feature.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/recent-freecad-macro-lessons/images/additive-pipe-path-and-profile.png&#34; width=&#34;45%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Sample code snippet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe_path_sketch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; body&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;newObject(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sketcher::SketchObject&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pin_pipe_path_sketch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe_path_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Support &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (flange_path_sketch_plane, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe_path_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;MapMode &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;FlatFace&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe_profile_sketch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; body&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;newObject(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sketcher::SketchObject&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pin_pipe_profile_sketch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe_profile_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Support &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [(pin_pipe_path_sketch, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Edge1&amp;#39;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe_profile_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;MapMode &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ObjectXZ&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; body&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;newObject(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PartDesign::AdditivePipe&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pin_pipe&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Profile &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pin_pipe_profile_sketch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Spine &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pin_pipe_path_sketch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As seen in the code snippet above, I also needed to use a new &lt;em&gt;MapMode&lt;/em&gt;. I had previously been using &lt;code&gt;MapMode = &#39;FlatFace&#39;&lt;/code&gt; by default everywhere.
Now I have a new level of understanding on just what &lt;em&gt;MapMode&lt;/em&gt; means&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;sketch-placement-and-rotation&#34;&gt;Sketch Placement and Rotation&lt;/h2&gt;
&lt;p&gt;When the same feature was needed on different sides of the brick (e.g. a stud on the front side and on the left side of a brick) I had
been relying on the fact that I was creating sketches programmatically.&lt;/p&gt;
&lt;p&gt;In other words, a sketch for the front side stud would
be created with different parts and constraints to that for the left side stud e.g. a horizontal &lt;em&gt;LineSegment&lt;/em&gt; in place of a vertical &lt;em&gt;LineSegment&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;However, this approach fell apart for the notch sketch as I was struggling to get the constraint solver to work for each of the four different
directions in which these sketches needed to be created.
I nearly ended up writing four completely separate chunks of code to create the same sketch shape: one for each direction.&lt;/p&gt;
&lt;p&gt;Clearly a better approach was needed, and obviously, FreeCAD provides one!&lt;/p&gt;
&lt;p&gt;The new, better and correct approach is to create the same sketch for all four directions, but to &lt;em&gt;rotate&lt;/em&gt; the Placement of the sketch depending on the direction.&lt;/p&gt;
&lt;p&gt;Sample code snippet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;label &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;right&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rotation &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;270&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_notch_sketch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; body&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;newObject(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sketcher::SketchObject&amp;#34;&lt;/span&gt;, label &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;_pin_notch_sketch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_notch_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Support &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [(datum_point, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_notch_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;MapMode &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Translate&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_notch_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Placement &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Placement(Vector(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;), Rotation(Vector(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;), rotation))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An example of two sketches, created by the same code, but rotated differently:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/recent-freecad-macro-lessons/images/sketch-placement-rotation.png&#34; width=&#34;90%&#34;/&gt; &lt;/figure&gt;
&lt;h2 id=&#34;bodytip-gotcha&#34;&gt;Body.Tip Gotcha&lt;/h2&gt;
&lt;p&gt;And finally, a &amp;rsquo;tip&amp;rsquo; about &lt;em&gt;Body.Tip&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;On most features, the following code will update the &lt;em&gt;Body.Tip&lt;/em&gt; to the new feature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_pipe &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; body&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;newObject(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PartDesign::AdditivePipe&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pin_pipe&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, for some reason (unknown to me), this will not update the &lt;em&gt;Body.Tip&lt;/em&gt; when adding particular features such as a &lt;em&gt;LinearPattern&lt;/em&gt; or &lt;em&gt;Mirrored&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Instead, the following WILL update the &lt;em&gt;Body.Tip&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pin_linear_pattern &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; doc&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;addObject(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PartDesign::LinearPattern&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pin_linear_pattern&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;body&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;addObject(pin_linear_pattern)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A successfully applied &lt;em&gt;LinearPattern&lt;/em&gt; with the &lt;em&gt;Body.Tip&lt;/em&gt; updated:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/recent-freecad-macro-lessons/images/technic-pin-linear-pattern.png&#34; width=&#34;90%&#34;/&gt; &lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/legify">legify</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>A Successfully Rendered FreeCAD Assembly</title>
            <link>https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/</link>
            <pubDate>Tue, 30 Mar 2021 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/</guid>
            <description>&lt;p&gt;I reached a milestone last weekend with a successful render of a brick assembly in FreeCAD.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_assembly_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;All brick models were created with the legify macro code available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks to some excellent FreeCAD developers I was able to create the assembly using
&lt;a href=&#34;https://github.com/Zolko-123/FreeCAD_Assembly4&#34;&gt;Assembly4 Workbench&lt;/a&gt; and
then render using &lt;a href=&#34;https://github.com/FreeCAD/FreeCAD-render&#34;&gt;Render Workbench&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve created a &lt;a href=&#34;models/bricks.zip&#34;&gt;zip&lt;/a&gt; of all the model files and below are some highlight renders and tech draw workbench diagrams.&lt;/p&gt;
&lt;p&gt;This was all done using the instructions I &lt;a href=&#34;https://vectronic.io/posts/building-freecad-on-macos-big-sur/&#34;&gt;posted previously&lt;/a&gt;
for getting the latest version of FreeCAD on Big Sur
running with the &lt;a href=&#34;https://github.com/FreeCAD/FreeCAD-render&#34;&gt;Render Workbench&lt;/a&gt; (with rendering performed by &lt;a href=&#34;https://www.cycles-renderer.org&#34;&gt;Cycles&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;For reference, the FreeCAD details used for this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;OS: macOS 10.16
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.20.24511 (Git)
Build type: Release
Branch: master
Hash: efa19683aee7fdcf4efbdec81acb0c947ee46f9b
Python version: 3.8.8
Qt version: 5.12.5
Coin version: 4.0.0
OCC version: 7.4.0
Locale: English/United Kingdom (en_GB)
&lt;/code&gt;&lt;/pre&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_assembly.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_assembly.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_1.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_4x2_1.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_4x2_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_4x2_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/technic_brick_4x1.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/technic_brick_4x1.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/technic_brick_4x1_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_1x1_front_stud.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_1x1_front_stud.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/a-successfully-rendered-freecad-assembly/images/brick_1x1_front_stud_render.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/legify">legify</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Building FreeCAD on macOS Big Sur</title>
            <link>https://vectronic.io/posts/building-freecad-on-macos-big-sur/</link>
            <pubDate>Mon, 15 Feb 2021 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/building-freecad-on-macos-big-sur/</guid>
            <description>&lt;p&gt;Presented here is a somewhat terse step-by-step guide to installing a working version of
&lt;a href=&#34;https://www.freecadweb.org&#34;&gt;FreeCAD&lt;/a&gt; 0.19 on macOS Big Sur using &lt;a href=&#34;https://docs.conda.io/en/latest/&#34;&gt;Conda&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Additional bonus steps explain how to use the new &lt;a href=&#34;https://github.com/mnesarco/FreeCAD_ExtMan&#34;&gt;FreeCAD Extension Manager&lt;/a&gt; to install the &lt;a href=&#34;https://github.com/Zolko-123/FreeCAD_Assembly4&#34;&gt;Assembly4 Workbench&lt;/a&gt; and
the &lt;a href=&#34;https://github.com/FreeCAD/FreeCAD-render&#34;&gt;Render Workbench&lt;/a&gt; (with rendering performed by &lt;a href=&#34;https://www.cycles-renderer.org&#34;&gt;Cycles&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you use a &lt;a href=&#34;https://www.3dconnexion.co.uk/spacemouse_wireless/uk/&#34;&gt;3DConnextion SpaceMouse&lt;/a&gt; I can report these steps will produce a build which supports it.&lt;/p&gt;
&lt;p&gt;The steps below are based on &lt;a href=&#34;https://vectronic.io/posts/building-freecad-with-3dconnexion-support-on-macos-using-conda/&#34;&gt;my initial post&lt;/a&gt; but updated to support the latest version of FreeCAD 0.19 and Big Sur
and to incorporate my further understanding of how this all works. Credit also goes to useful information from
DrVAX&amp;rsquo;s &lt;a href=&#34;https://drvax.com/freecad-pre-releases-on-macos/&#34;&gt;blog post&lt;/a&gt; and many contributions on this &lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?f=4&amp;amp;t=51345&#34;&gt;forum thread&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE 1&lt;/strong&gt;: These instructions worked using macOS Big Sur 11.2.1 with code repositories and release artifacts
available on Feb 15 2021. Your results may vary depending on when you attempt these instructions and what version of macOS is installed &amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE 2&lt;/strong&gt;: I am not sure if this is necessary, but to avoid confusion, before starting, I removed the following items from my system which I had previously installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;XCode.app&lt;/em&gt; was removed by deleting it from the &lt;code&gt;/Applications&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;XCode CommandLineTools&lt;/em&gt; was removed by deleting it from the &lt;code&gt;/Library/Developer&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Brew&lt;/em&gt; was removed via &lt;code&gt;/bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You do not necessarily need to do the above, but if you are having any issues with the instructions below, maybe try removing some of these if they are already installed&amp;hellip;&lt;/p&gt;
&lt;p&gt;Also, &lt;em&gt;XCode CommandLineTools&lt;/em&gt; is required later, so instructions to install this do appear further below at the appropriate place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE 3&lt;/strong&gt;: To avoid confusion, all instructions are executed within the initially created Conda environment so that there should be minimal dependency on pre-installed build tools etc.&lt;/p&gt;
&lt;h4 id=&#34;install-3dconnexion-drivers&#34;&gt;Install 3DConnexion drivers&lt;/h4&gt;
&lt;p&gt;Download and install the &lt;a href=&#34;https://3dconnexion.com/uk/support/faq/beta-driver-for-macos-11-big-sur/&#34;&gt;beta driver for macOS Big Sur&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;install-miniconda&#34;&gt;Install miniconda&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
curl -L -O https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
bash Miniconda3-latest-MacOSX-x86_64.sh -b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NOTE: Replace &lt;code&gt;&amp;lt;home&amp;gt;&lt;/code&gt; below with your home directory e.g. &lt;code&gt;/Users/vectronic&lt;/code&gt; or possibly &lt;code&gt;$HOME&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo &amp;quot;. &amp;lt;home&amp;gt;/miniconda3/etc/profile.d/conda.sh&amp;quot; &amp;gt;&amp;gt; ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Close and restart your terminal.&lt;/p&gt;
&lt;h4 id=&#34;prepare-conda-environment&#34;&gt;Prepare Conda environment&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda create -n freecad_0_19 -y
conda activate freecad_0_19
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From now on, all instructions should be performed within the activated &lt;code&gt;freecad_0_19&lt;/code&gt; environment.
If you open a new terminal to carry on, or whenever you want to run FreeCAD, you will first need to run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conda activate freecad_0_19
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DrVax provides helpful instructions on how the final installed &lt;code&gt;freecad&lt;/code&gt; executable can be run as a macOS application.
See &amp;ldquo;Creating a macOS Application from a Conda Installation&amp;rdquo; on &lt;a href=&#34;https://drvax.com/freecad-pre-releases-on-macos/&#34;&gt;this page&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;install-freecad&#34;&gt;Install FreeCAD&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda install -c freecad/label/dev freecad -y
conda install libclang=9.0.1 -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;libclang&lt;/code&gt; command is a workaround for problems launching FreeCAD on Big Sur.&lt;/p&gt;
&lt;h4 id=&#34;see-if-it-works&#34;&gt;See if it works&lt;/h4&gt;
&lt;p&gt;Start FreeCAD:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;freecad
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If FreeCAD starts up (and doesn&amp;rsquo;t hang), things are looking good&amp;hellip;&lt;/p&gt;
&lt;p&gt;Exit FreeCAD and go back to the &lt;code&gt;freecad_0_19&lt;/code&gt; Conda environment in the terminal.&lt;/p&gt;
&lt;h4 id=&#34;install-xcode-command-line-tools&#34;&gt;Install Xcode command line tools&lt;/h4&gt;
&lt;p&gt;Trigger the installation with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;xcode-select --install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Follow the instructions and once installed make sure they are in use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo xcode-select -s /Library/Developer/CommandLineTools
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;install-extension-manager-workbench&#34;&gt;Install Extension Manager workbench&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;mkdir ~/Library/Preferences/FreeCAD/Mod
cd ~/Library/Preferences/FreeCAD/Mod
git clone https://github.com/mnesarco/FreeCAD_ExtMan.git ExtMan
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;install-cycles-standalone&#34;&gt;Install cycles standalone&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;conda install svn cmake -y
cd /tmp
mkdir cycles
cd cycles
mkdir lib
cd lib
svn checkout -r 62553 https://svn.blender.org/svnroot/bf-blender/trunk/lib/darwin
cd ..
git clone git://git.blender.org/cycles.git
cd cycles
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit &lt;code&gt;src/cmake/Modules/FindOpenImageIO.cmake&lt;/code&gt; and change line 70 from &lt;code&gt;TRUE&lt;/code&gt; to &lt;code&gt;FALSE&lt;/code&gt; e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SET(OPENIMAGEIO_PUGIXML_FOUND FALSE)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit &lt;code&gt;src/cmake/external_libs.cmake&lt;/code&gt; and change line 235 from &lt;code&gt;PugiXML&lt;/code&gt; to &lt;code&gt;PUGIXML&lt;/code&gt; e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find_package(PUGIXML REQUIRED)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PUGIXML_ROOT_DIR=/tmp/cycles/lib/darwin/pugixml make
cp bin-opt/bin/cycles ~/miniconda3/envs/freecad_0_19/bin/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;freecad-configuration&#34;&gt;FreeCAD configuration&lt;/h3&gt;
&lt;p&gt;Start FreeCAD:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;freecad
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&#34;install-assembly4-using-extension-manager-workbench&#34;&gt;Install Assembly4 using Extension Manager Workbench&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;em&gt;View-&amp;gt;Workbench-&amp;gt;Extension Manager&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;Add (Download)&lt;/em&gt; and then &lt;em&gt;Addons&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Look in the &lt;em&gt;Assembly&lt;/em&gt; section for &lt;em&gt;Assembly4&lt;/em&gt; and click &lt;em&gt;Install&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Confirm &lt;em&gt;Install&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id=&#34;install-render-workbench-using-extension-manager-workbench&#34;&gt;Install Render Workbench using Extension Manager Workbench&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;Go back to &lt;em&gt;Add (Download)&lt;/em&gt; and then &lt;em&gt;Addons&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Look in the &lt;em&gt;Uncategorized&lt;/em&gt; section for &lt;em&gt;Render&lt;/em&gt; and click &lt;em&gt;Install&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Confirm &lt;em&gt;Install&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Restart FreeCAD.&lt;/p&gt;
&lt;h4 id=&#34;configure-render-workbench-to-use-cycles&#34;&gt;Configure Render Workbench to use Cycles&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Load the Render workbench: &lt;em&gt;View-&amp;gt;Workbench-&amp;gt;Render&lt;/em&gt; (this might hang for a bit&amp;hellip;).&lt;/li&gt;
&lt;li&gt;Configure the render workbench via &lt;em&gt;freecad-&amp;gt;Preferences-&amp;gt;Render&lt;/em&gt; and set:
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Cycles executable path&lt;/em&gt; to &lt;code&gt;cycles&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Render parameters&lt;/em&gt; to &lt;code&gt;--samples 500 --background&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;test-part-design-model-render&#34;&gt;Test Part Design model render&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Download this &lt;a href=&#34;models/brick_4x2.FCStd&#34;&gt;sample part design model&lt;/a&gt; and open it in FreeCAD.&lt;/li&gt;
&lt;li&gt;Create a render project via &lt;em&gt;Render-&amp;gt;Cycles Project&lt;/em&gt; and selecting the &lt;code&gt;cycles_sunlight.xml&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Change the &lt;em&gt;Angular Deflection&lt;/em&gt; data property of the Cycles Project from &lt;code&gt;0.52&lt;/code&gt; to &lt;code&gt;0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the tree navigation, select the &lt;em&gt;brick-&amp;gt;top_studs_inside_pocket&lt;/em&gt; AND the &lt;em&gt;Cycles Project&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Create a render view via &lt;em&gt;Render-&amp;gt;Create View&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Ensure the view is set to perspective via &lt;em&gt;View-&amp;gt;Perspective View&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;em&gt;Cycles Project&lt;/em&gt; in the tree navigation.&lt;/li&gt;
&lt;li&gt;Render via &lt;em&gt;Render-&amp;gt;Render&lt;/em&gt; (this will hang for a bit&amp;hellip; you can see progress in the terminal where you launched FreeCAD).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should end up with a rendered image similar to this:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/building-freecad-on-macos-big-sur/images/brick_4x2.png&#34;/&gt; &lt;/figure&gt;
&lt;h4 id=&#34;test-assembly4-model-render&#34;&gt;Test Assembly4 model render&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Download this &lt;a href=&#34;models/bricks.FCStd&#34;&gt;sample assembly4 model&lt;/a&gt; and open it in FreeCAD.&lt;/li&gt;
&lt;li&gt;Create a render project via &lt;em&gt;Render-&amp;gt;Cycles Project&lt;/em&gt; and selecting the &lt;code&gt;cycles_sunlight.xml&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Change the &lt;em&gt;Angular Deflection&lt;/em&gt; data property of the Cycles Project from &lt;code&gt;0.52&lt;/code&gt; to &lt;code&gt;0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the tree navigation, select the &lt;em&gt;Model&lt;/em&gt; AND the &lt;em&gt;Cycles Project&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Create a render view via &lt;em&gt;Render-&amp;gt;Create View&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Ensure the view is set to perspective via &lt;em&gt;View-&amp;gt;Perspective View&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;em&gt;Cycles Project&lt;/em&gt; in the tree navigation.&lt;/li&gt;
&lt;li&gt;Render via &lt;em&gt;Render-&amp;gt;Render&lt;/em&gt; (this will hang for a bit&amp;hellip; you can see progress in the terminal where you launched FreeCAD).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should end up with a rendered image similar to this:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/building-freecad-on-macos-big-sur/images/bricks.png&#34;/&gt; &lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Migrate to Deno?</title>
            <link>https://vectronic.io/posts/migrate-to-deno/</link>
            <pubDate>Fri, 08 Jan 2021 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/migrate-to-deno/</guid>
            <description>&lt;p&gt;The plan for &lt;a href=&#34;https://github.com/flowscripter&#34;&gt;Flowscripter&lt;/a&gt; has always included the following goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use TypeScript.&lt;/li&gt;
&lt;li&gt;Use dynamic import of ES modules.&lt;/li&gt;
&lt;li&gt;Rely on existing module dependency directives to auto-install plugin dependencies i.e. not inventing a new module dependency framework.&lt;/li&gt;
&lt;li&gt;Providing Flowscripter as a single downloadable binary with no need for pre-installed dependencies e.g. Node.js, ffmpeg.&lt;/li&gt;
&lt;li&gt;Support native extensions written in Rust.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To meet these requirements Flowscripter started with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TypeScript running on Node.js.&lt;/li&gt;
&lt;li&gt;Requiring Node.js 10.x onwards which had the first experimental support for ES modules.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://github.com/flowscripter/esm-dynamic-plugins&#34;&gt;esm-dynamic-plugins&lt;/a&gt; library made use of the &lt;a href=&#34;https://www.npmjs.com&#34;&gt;npmjs.com repository&lt;/a&gt; and Node.js &lt;code&gt;package.js&lt;/code&gt; definitions.
For browser runtimes, using &lt;a href=&#34;https://unpkg.com&#34;&gt;https://unpkg.com&lt;/a&gt; was the intention.&lt;/li&gt;
&lt;li&gt;The intention was to use &lt;a href=&#34;https://github.com/nexe/nexe&#34;&gt;nexe&lt;/a&gt; to build a single distributable binary.&lt;/li&gt;
&lt;li&gt;The intention was to use NodeJS N-API C++/C addon support and develop Rust based native add-ons as per this &lt;a href=&#34;https://blog.logrocket.com/rust-and-node-js-a-match-made-in-heaven/&#34;&gt;tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course with the above technologies, came the usual (and painful) need to configure and debug a build toolchain providing TypeScript, a test framework (&lt;a href=&#34;https://jestjs.io&#34;&gt;Jest&lt;/a&gt;),
a packaging system (&lt;a href=&#34;https://rollupjs.org/guide/en/&#34;&gt;RollupJs&lt;/a&gt;) and a documentation generator (&lt;a href=&#34;https://typedoc.org&#34;&gt;TypeDoc&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;More difficult was the need for these
tools to support ES modules natively (or via transpiling) and for the Flowscripter ES Modules to depend on existing non-ES module NodeJS packages &amp;hellip;.
I think I spent just as much time getting the toolchain working together as I did writing &amp;lsquo;actual code&amp;rsquo;&amp;hellip;&lt;/p&gt;
&lt;p&gt;Although, the Flowscripter &amp;lsquo;actual code&amp;rsquo; it still in a state of infancy, the main concerns so far with the above are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making use of the NodeJS &lt;code&gt;package.json&lt;/code&gt; and &lt;a href=&#34;https://www.npmjs.com&#34;&gt;npm repository&lt;/a&gt; either necessitated:
&lt;ul&gt;
&lt;li&gt;Calling out to a locally installed &lt;code&gt;npm&lt;/code&gt; thereby defeating the purpose of a single installable binary.&lt;/li&gt;
&lt;li&gt;Importing the underlying &lt;code&gt;npm&lt;/code&gt; implementation: a horrible rabbit hole I discovered and then exited!&lt;/li&gt;
&lt;li&gt;Implementing support from scratch - which was done but with some severe limitations (see &lt;a href=&#34;https://github.com/flowscripter/cli-framework/blob/master/src/plugin/command/NpmPackageUtils.ts#L34-L45&#34;&gt;here&lt;/a&gt; and
&lt;a href=&#34;https://github.com/flowscripter/esm-dynamic-plugins/issues/281&#34;&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Despite the excellence of nexe, support for native addons, externally sourced modules and ESM modules still seems to be work in progress&amp;hellip; see &lt;a href=&#34;https://github.com/nexe/nexe/issues/811&#34;&gt;here&lt;/a&gt;, &lt;a href=&#34;https://github.com/nexe/nexe/issues/639&#34;&gt;here&lt;/a&gt; and &lt;a href=&#34;https://github.com/nexe/nexe/issues/815&#34;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Around the time of starting out on Flowscripter I had seen the &lt;a href=&#34;https://www.youtube.com/watch?v=M3BM9TB-8yA&#34;&gt;announcement of Deno&lt;/a&gt;.
Obviously bleeding edge would have been an understatement at that point&amp;hellip;&lt;/p&gt;
&lt;p&gt;However, since then, time has passed (mostly working on the toolchain issues mentioned above, or more importantly on actual paid work&amp;hellip;.) and Deno v1 has been released.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s tempting. Let&amp;rsquo;s review given the initially stated Flowscripter goals and the current concerns for the Node.js based implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TypeScript ✅&lt;/li&gt;
&lt;li&gt;ES Modules ✅&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/keroxp/deno_plugin_example&#34;&gt;Rust plugins&lt;/a&gt; ✅&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://deno.land/manual/tools/compiler#compiling-executables&#34;&gt;Compiled executables&lt;/a&gt; ✅&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://deno.land/manual#comparison-to-nodejs&#34;&gt;Simple dependency mechanism&lt;/a&gt; ✅&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, the support for importing a module from a URL would (hopefully) completely obviate the need for &lt;a href=&#34;https://github.com/flowscripter/esm-dynamic-plugins&#34;&gt;esm-dynamic-plugins&lt;/a&gt; to implement
separate a &lt;code&gt;UrlPluginRepository.ts&lt;/code&gt; and &lt;code&gt;NodeModulesPluginRepository.ts&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course there are arguments against Deno. These are mostly based on it&amp;rsquo;s relative immaturity. Fair enough, you don&amp;rsquo;t want to back the wrong horse&amp;hellip; And also is it really ready for production?&lt;/p&gt;
&lt;p&gt;To answer that, I&amp;rsquo;m going to take some time out to do an analysis of whether the above mentioned features can currently meet the Flowscripter goals and my concerns on the current path taken.
Findings to follow&amp;hellip;.&lt;/p&gt;
&lt;p&gt;P.S. I&amp;rsquo;m also going to take time to make use of the fact that GitHub seems to be swallowing the CI/CD world. Hence I&amp;rsquo;m planning to port away from &lt;a href=&#34;https://www.npmjs.com&#34;&gt;npmjs.com&lt;/a&gt;
(well maybe with Deno this won&amp;rsquo;t be relevant - any hoo&amp;hellip;), &lt;a href=&#34;https://travis-ci.com&#34;&gt;Travis&lt;/a&gt; and &lt;a href=&#34;https://github.com/renovatebot/renovate&#34;&gt;Renovate&lt;/a&gt; and use GitHub for everything.&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/deno">deno</category>
            <category domain="https://vectronic.io/tags/flowscripter">flowscripter</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Legify 0.2.2</title>
            <link>https://vectronic.io/posts/legify-0.2.2/</link>
            <pubDate>Sun, 02 Aug 2020 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/legify-0.2.2/</guid>
            <description>&lt;p&gt;A bugix version of Legify is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.2.2&#34;&gt;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.2.2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It provides improvements to measurements and rendering based on using the macro generated parts
in Assembly V4 and TechDraw workbenches.&lt;/p&gt;
&lt;p&gt;Example TechDraw diagrams for individual parts and assemblies are provided below.&lt;/p&gt;
&lt;p&gt;The latest macro code, brief overview and instructions are available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_assembly.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.2.2/images/brick_assembly.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_1_of_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.2.2/images/brick_4x2_1_of_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_4x2_2_of_2.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.2.2/images/brick_4x2_2_of_2.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/technic_brick_4x1.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.2.2/images/technic_brick_4x1.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;

&lt;figure&gt;
&lt;a href=&#34;images/brick_1x1_front_stud.pdf&#34;&gt;
&lt;img src=&#34;https://vectronic.io/posts/legify-0.2.2/images/brick_1x1_front_stud.png&#34; width=&#34;50%&#34;/&gt; &lt;/a&gt;&lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/release">release</category>
            <category domain="https://vectronic.io/tags/freecad">freecad</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>FFmpeg now supports ICC Profiles in MP4</title>
            <link>https://vectronic.io/posts/ffmpeg-now-supports-icc-profiles-in-mp4/</link>
            <pubDate>Mon, 16 Mar 2020 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/ffmpeg-now-supports-icc-profiles-in-mp4/</guid>
            <description>&lt;p&gt;Last year I provided some FFmpeg patches to support &lt;a href=&#34;http://www.color.org/specification/ICC1v43_2010-12.pdf&#34;&gt;ICC Profiles&lt;/a&gt;
stored within MP4 (and MOV) files.&lt;/p&gt;
&lt;p&gt;The patches were recently merged into master and will therefore be available in the next FFmpeg release.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\( ﾟヮﾟ)/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;ICC profiles can be stored in MOV/MP4 sample descriptor colour information atoms.
The relevant extract from the &lt;a href=&#34;https://standards.iso.org/ittf/PubliclyAvailableStandards/c068960_ISO_IEC_14496-12_2015.zip&#34;&gt;ISO standard&lt;/a&gt; is:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;class ColourInformationBox extends Box(&amp;#39;colr&amp;#39;){
    unsigned int(32) colour_type;
    if (colour_type == &amp;#39;nclx&amp;#39;)  /* on-screen colours */
    {
        unsigned int(16) colour_primaries;
        unsigned int(16) transfer_characteristics;
        unsigned int(16) matrix_coefficients;
        unsigned int(1)  full_range_flag;
        unsigned int(7)  reserved = 0;
    }
    else if (colour_type == &amp;#39;rICC&amp;#39;)
    {
        ICC_profile;    // restricted ICC profile
    }
    else if (colour_type == &amp;#39;prof&amp;#39;)
    {
        ICC_profile;    // unrestricted ICC profile
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;FFmpeg already had support for the &lt;code&gt;nclx&lt;/code&gt; colour type, but my use case was to support the &lt;code&gt;prof&lt;/code&gt; colour type.&lt;/p&gt;
&lt;p&gt;Additionally, ICC profile support was already available on a per frame basis in
&lt;code&gt;AVFrameSideDataType.AV_FRAME_DATA_ICC_PROFILE&lt;/code&gt;. This is used by the PNG, WEBP and MJPEG codec implementations.
This support was not sufficient however as the MOV/MP4 sample descriptor relates to the entire stream and not on a per-frame basis.&lt;/p&gt;
&lt;h4 id=&#34;changes&#34;&gt;Changes&lt;/h4&gt;
&lt;p&gt;The changes required were to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/FFmpeg/FFmpeg/commit/05d27f342be28cf92f3c9470e701834c416cad89&#34;&gt;add a new enum value&lt;/a&gt; &lt;code&gt;AV_PKT_DATA_ICC_PROFILE&lt;/code&gt; to &lt;code&gt;AVPacketSideDataType&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;add reading support to the MP4 &lt;a href=&#34;https://github.com/FFmpeg/FFmpeg/commit/472e044587d5fe43bbc84713ca824fd8350924b8&#34;&gt;demuxer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;add writing support to the MP4 &lt;a href=&#34;https://github.com/FFmpeg/FFmpeg/commit/dc1c3c640d245bc3e7a7a4c82ae1a6d06343abab&#34;&gt;muxer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last item included adding a movflag &lt;code&gt;prefer_icc&lt;/code&gt; to ensure backwards compatible behaviour of the existing &lt;code&gt;write_colr&lt;/code&gt; movflag.&lt;/p&gt;
&lt;h4 id=&#34;usage&#34;&gt;Usage&lt;/h4&gt;
&lt;p&gt;Here is a small example file with an ICC Profile embedded: &lt;a href=&#34;http://vectronic.io/icc-profile/icc-profile.mp4&#34;&gt;icc-profile.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the above changes in place and using the sample file, when you execute &lt;code&gt;ffprobe&lt;/code&gt; you will see the output includes a new side data entry of &lt;code&gt;ICC Profile&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% ./ffprobe -hide_banner icc-profile.mp4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Input &lt;span style=&#34;color:#75715e&#34;&gt;#0, mov,mp4,m4a,3gp,3g2,mj2, from &amp;#39;icc-profile.mp4&amp;#39;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    major_brand     : mp42
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    minor_version   : &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    compatible_brands: mp41mp42isom
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    creation_time   : 2019-09-19T08:13:20.000000Z
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Duration: 00:00:00.08, start: 0.000000, bitrate: &lt;span style=&#34;color:#ae81ff&#34;&gt;32519&lt;/span&gt; kb/s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Stream &lt;span style=&#34;color:#75715e&#34;&gt;#0:0(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, progressive), 3440x1440 [SAR 1:1 DAR 43:18], 31699 kb/s, 60 fps, 60 tbr, 600 tbn, 600 tbc (default)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      creation_time   : 2019-09-19T08:13:20.000000Z
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      handler_name    : Core Media Video
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Side data:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ICC Profile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When remuxing an MP4, the following will preserve the ICC profile in the output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./ffmpeg -i icc-profile.mp4 -movflags write_colr+prefer_icc -c:v copy out.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/ffmpeg">ffmpeg</category>
            <category domain="https://vectronic.io/tags/media">media</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Legify 0.2.0</title>
            <link>https://vectronic.io/posts/legify-0.2.0/</link>
            <pubDate>Sun, 15 Mar 2020 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/legify-0.2.0/</guid>
            <description>&lt;p&gt;The latest and most likely last version of Legify is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.2.0&#34;&gt;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.2.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve achieved my goals with this project, which were to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get to grips with FreeCAD and parametric modelling concepts: sketches, constraints, datum planes etc.&lt;/li&gt;
&lt;li&gt;Learn Python and use it for FreeCAD scripting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m now moving on to learn about assemblies and technical drawings.&lt;/p&gt;
&lt;p&gt;The latest macro code, brief overview and instructions are available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/python">python</category>
            <category domain="https://vectronic.io/tags/release">release</category>
            <category domain="https://vectronic.io/tags/freecad">freecad</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Measurement of Lego Brick Dimensions</title>
            <link>https://vectronic.io/posts/measurement-of-lego-brick-dimensions/</link>
            <pubDate>Mon, 01 Jul 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/measurement-of-lego-brick-dimensions/</guid>
            <description>&lt;p&gt;As part of my efforts to &lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;accurately model Lego bricks&lt;/a&gt;,
I need to visualise the finer features of Lego pieces and measure various dimensions accurately.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/measurement-of-lego-brick-dimensions/images/stud.jpg&#34; width=&#34;40%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;I&amp;rsquo;ve been making measurements using the following microscopy setup:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/measurement-of-lego-brick-dimensions/images/setup.jpg&#34; width=&#34;80%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Measurements were made using a calibrated scale of 0.1mm:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/measurement-of-lego-brick-dimensions/images/scale.jpg&#34; width=&#34;80%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Here is a good example of the usefulness of this approach over measurement by hand with a micrometer:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/measurement-of-lego-brick-dimensions/images/axle_pin.jpg&#34; width=&#34;80%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;So far, two bricks have been regrettably sacrificed to obtain some internal dimensions:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/measurement-of-lego-brick-dimensions/images/sacrificial_brick.jpg&#34; width=&#34;80%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;All photos are posted to my &lt;a href=&#34;https://www.pinterest.co.uk/vectronic/lego-measurement&#34;&gt;Lego Measurement&lt;/a&gt; Pinterest board.&lt;/p&gt;
&lt;p&gt;Stay tuned for a new release of &lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;Legify&lt;/a&gt; with new features
incorporating these measurements.&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/lego">lego</category>
            <category domain="https://vectronic.io/tags/microscopy">microscopy</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Timecodes in Excel without Macros</title>
            <link>https://vectronic.io/posts/timecodes-in-excel-without-macros/</link>
            <pubDate>Mon, 17 Jun 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/timecodes-in-excel-without-macros/</guid>
            <description>&lt;p&gt;Googling for &amp;ldquo;excel timecode&amp;rdquo; didn&amp;rsquo;t produce any results which met my requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support 29.97 drop-frame SMPTE timecode&lt;/li&gt;
&lt;li&gt;calculate a duration given an in-point and out-point&lt;/li&gt;
&lt;li&gt;provide conversion to and from timecode, frame count and microseconds&lt;/li&gt;
&lt;li&gt;not based on Excel macros so that the solution can be easily redistributed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because of this, I am pleased to present a solution which does meet the above requirements:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/timecode-spreadsheet&#34;&gt;https://github.com/vectronic/timecode-spreadsheet&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/excel">excel</category>
            <category domain="https://vectronic.io/tags/media">media</category>
            <category domain="https://vectronic.io/tags/timecode">timecode</category>
            <category domain="https://vectronic.io/tags/release">release</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Building FreeCAD Assembly3 on macOS using Conda</title>
            <link>https://vectronic.io/posts/building-freecad-assembly3-on-macos-using-conda/</link>
            <pubDate>Thu, 13 Jun 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/building-freecad-assembly3-on-macos-using-conda/</guid>
            <description>&lt;p&gt;I have moved on from learning basic part design and scripting in FreeCAD and now want to tackle assemblies.&lt;/p&gt;
&lt;p&gt;Following on from my previous post,
&lt;a href=&#34;https://vectronic.io/posts/building-freecad-with-3dconnexion-support-on-macos-using-conda&#34;&gt;Building FreeCAD with 3DConnexion Support on macOS using Conda&lt;/a&gt;,
this post presents similar instructions for building the very promising
&lt;a href=&#34;https://github.com/realthunder/FreeCAD_assembly3&#34;&gt;Assembly3 Workbench for FreeCAD&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Again, I wanted to use the latest source AND use a &lt;a href=&#34;https://www.3dconnexion.co.uk/spacemouse_wireless/uk/&#34;&gt;3DConnexion SpaceMouse&lt;/a&gt; on a MacBook Pro.
Using Conda and the &lt;a href=&#34;https://github.com/conda-forge/freecad-feedstock&#34;&gt;Conda Forge feedstock for FreeCAD&lt;/a&gt; makes this a
scriptable, repeatable process.&lt;/p&gt;
&lt;h4 id=&#34;install-3dconnexion-drivers&#34;&gt;Install 3DConnexion Drivers&lt;/h4&gt;
&lt;p&gt;Download and install the latest &lt;a href=&#34;https://www.3dconnexion.co.uk/service/drivers.html&#34;&gt;driver for macOS&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;install-miniconda&#34;&gt;Install miniconda&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;curl -L -O https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
bash Miniconda3-latest-MacOSX-x86_64.sh -b
rm Miniconda3-latest-MacOSX-x86_64.sh 
echo &amp;quot;. ~/miniconda3/etc/profile.d/conda.sh&amp;quot; &amp;gt;&amp;gt; ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;install-macosx109sdk&#34;&gt;Install MacOSX10.9.sdk&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;curl -L -O https://github.com/phracker/MacOSX-SDKs/releases/download/10.13/MacOSX10.9.sdk.tar.xz
sudo tar -C /opt/ -xf MacOSX10.9.sdk.tar.xz 
rm MacOSX10.9.sdk.tar.xz
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;set-sdk-location-for-conda&#34;&gt;Set SDK location for Conda&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &amp;quot;CONDA_BUILD_SYSROOT:&amp;quot; &amp;gt; ~/conda_build_config.yaml
echo &amp;quot;   - /opt/MacOSX10.9.sdk  # [osx]&amp;quot; &amp;gt;&amp;gt; ~/conda_build_config.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;link-to-sdk-for-circle-ci-based-support-scripts&#34;&gt;Link to SDK for Circle CI based support scripts&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
ln -s /opt/MacOSX10.9.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;prepare-conda-environment&#34;&gt;Prepare Conda environment&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda create -n freecad_ass3 -y
conda activate freecad_ass3
conda config --add channels conda-forge
conda install conda-build -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;get-freecad-feedstock&#34;&gt;Get FreeCAD feedstock&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/conda-forge/freecad-feedstock
cd freecad-feedstock/
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;point-to-the-assembly3-freecad-fork&#34;&gt;Point to the Assembly3 FreeCAD Fork&lt;/h4&gt;
&lt;p&gt;The FreeCAD feedstock recipe needs to be modified to use &lt;a href=&#34;https://github.com/realthunder/FreeCAD&#34;&gt;realthunder&amp;rsquo;s FreeCAD Fork&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Edit &lt;code&gt;recipe/meta.yaml&lt;/code&gt; and edit the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;version&lt;/code&gt; variable: &lt;code&gt;{% set version = &amp;quot;LinkStage3&amp;quot; %}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;git_url&lt;/code&gt; variable: &lt;code&gt;git_url: https://github.com/realthunder/FreeCAD.git&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;build-freecad&#34;&gt;Build FreeCAD&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda build ./recipe -m ./.ci_support/osx_python3.7.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;workaround-failing-tests&#34;&gt;Workaround failing tests&lt;/h4&gt;
&lt;p&gt;The build will finally fail with a message similar to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Tests failed for freecad-LinkStage3-py37h7748daf_1.tar.bz2 - moving package to /Users/vectronic/miniconda3/envs/freecad_ass3/conda-bld/broken
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The failed tests don&amp;rsquo;t seem to stop basic functionality working in FreeCAD and realthunder is planning to eventually fix them.
In the meantime I ignore them as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mv ~/miniconda3/envs/freecad_ass3/conda-bld/broken/freecad-LinkStage3-py37h7748daf_1.tar.bz2  ~/miniconda3/envs/freecad_ass3/conda-bld/osx-64/
conda index ~/miniconda3/envs/freecad_ass3/conda-bld
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;install-freecad&#34;&gt;Install FreeCAD&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda install -c file://${CONDA_PREFIX}/conda-bld/ freecad=LinkStage3 -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;install-and-build-the-assembly3-workbench-and-constraint-solver&#34;&gt;Install and build the Assembly3 workbench and constraint solver&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda install swig -y

cd ~/miniconda3/envs/freecad_ass3/Ext/freecad
git clone https://github.com/realthunder/FreeCAD_assembly3.git
mv FreeCAD_assembly3 asm3
cd asm3

git checkout f66358d
git submodule update --init slvs
cd slvs
git submodule update --init --recursive

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON=1 ..
make _slvs

cd ../..
touch py_slvs_mac/__init__.py
cp slvs/build/src/swig/python/_slvs.so py_slvs_mac/
cp slvs/build/src/swig/python/slvs.py py_slvs_mac/

cd py_slvs_mac
install_name_tool -id &amp;quot;_slvs.so&amp;quot; _slvs.so
install_name_tool -add_rpath &amp;quot;@loader_path/../../../../lib/&amp;quot; _slvs.so

install_name_tool -change &amp;quot;~/miniconda3/envs/freecad_ass3/lib/libpython3.7m.dylib&amp;quot; &amp;quot;@rpath/Python&amp;quot; _slvs.so
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: If the last command didn&amp;rsquo;t work as the python library version has changed, run the following to see which library to relink to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;otool -L _slvs.so
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;use-it&#34;&gt;Use it!&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;FreeCAD
&lt;/code&gt;&lt;/pre&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>First Microscopic Soldering Project</title>
            <link>https://vectronic.io/posts/first-microscopic-soldering-project/</link>
            <pubDate>Mon, 10 Jun 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/first-microscopic-soldering-project/</guid>
            <description>&lt;p&gt;My first serious microscopic soldering project took place over the weekend!&lt;/p&gt;
&lt;p&gt;An Intel NUC had been &lt;em&gt;prised&lt;/em&gt; open during a baggage inspection. Thanks TSA!&lt;/p&gt;
&lt;p&gt;As a result the fan connector had been torn from the PCB.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not saying it was a nicely executed repair, but the NUC does now work&amp;hellip; Identified areas for improvement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an improved solder flux situation: my 0.2mm solder didn&amp;rsquo;t want to flow onto anything, the thicker solder dumped
a pool of flux eveywhere.&lt;/li&gt;
&lt;li&gt;an improved glueing mechanism: again, I ended up with a pool of super glue&amp;hellip;&lt;/li&gt;
&lt;li&gt;improved software settings for the microscope&amp;rsquo;s USB camera: the photos don&amp;rsquo;t do justice to the stunning
clarity I had through the eye pieces.&lt;/li&gt;
&lt;li&gt;a PCB cleaning mechanism.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Firstly, the workstation setup:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/setup.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;The damage inflicted on the innocent electronics:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/broken.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;A messy scrape to discover and expose some tracks which hadn&amp;rsquo;t been ripped off:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/exposed.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Rewired links (and that pool of flux):&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/linked_1.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/linked_2.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/linked_3.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;A big dollop of epoxy resin glue to hold the fan connector down:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/glued.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;A zoomed out view of the completed repair:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/first-microscopic-soldering-project/images/fixed.jpg&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/electronics">electronics</category>
            <category domain="https://vectronic.io/tags/microscopy">microscopy</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Building FreeCAD with 3DConnexion Support on macOS using Conda</title>
            <link>https://vectronic.io/posts/building-freecad-with-3dconnexion-support-on-macos-using-conda/</link>
            <pubDate>Sat, 04 May 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/building-freecad-with-3dconnexion-support-on-macos-using-conda/</guid>
            <description>&lt;p&gt;Presented here is a somewhat terse step-by-step guide to building FreeCAD from source using Conda and
the &lt;a href=&#34;https://github.com/conda-forge/freecad-feedstock&#34;&gt;Conda Forge feedstock for FreeCAD&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I need to do this to ensure I can run the latest FreeCAD code AND use a
&lt;a href=&#34;https://www.3dconnexion.co.uk/spacemouse_wireless/uk/&#34;&gt;3DConnexion SpaceMouse&lt;/a&gt; on a MacBook Pro.&lt;/p&gt;
&lt;p&gt;The steps below were compiled through trial and error, much hair-pulling and extraction of useful information from
&lt;a href=&#34;https://github.com/FreeCAD/FreeCAD_Conda/blob/master/build.md#osx&#34;&gt;here&lt;/a&gt;,
&lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?style=4&amp;amp;f=3&amp;amp;t=29766&amp;amp;start=50&#34;&gt;here&lt;/a&gt; and
&lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?f=4&amp;amp;t=34608&amp;amp;p=305702#p305702&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;install-3dconnexion-drivers&#34;&gt;Install 3DConnexion Drivers&lt;/h4&gt;
&lt;p&gt;Download and install the latest &lt;a href=&#34;https://www.3dconnexion.co.uk/service/drivers.html&#34;&gt;driver for macOS&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;install-miniconda&#34;&gt;Install miniconda&lt;/h4&gt;
&lt;p&gt;NOTE: Replace &lt;code&gt;&amp;lt;home&amp;gt;&lt;/code&gt; below with your home directory e.g. &lt;code&gt;/Users/vectronic&lt;/code&gt; or possibly &lt;code&gt;$HOME&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -L -O https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
bash Miniconda3-latest-MacOSX-x86_64.sh -b
rm Miniconda3-latest-MacOSX-x86_64.sh 
echo &amp;quot;. &amp;lt;home&amp;gt;/miniconda3/etc/profile.d/conda.sh&amp;quot; &amp;gt;&amp;gt; ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;install-macosx109sdk&#34;&gt;Install MacOSX10.9.sdk&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;curl -L -O https://github.com/phracker/MacOSX-SDKs/releases/download/10.13/MacOSX10.9.sdk.tar.xz
sudo tar -C /opt/ -xf MacOSX10.9.sdk.tar.xz 
rm MacOSX10.9.sdk.tar.xz
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;set-sdk-location-for-conda&#34;&gt;Set SDK location for Conda&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &amp;quot;CONDA_BUILD_SYSROOT:&amp;quot; &amp;gt; ~/conda_build_config.yaml
echo &amp;quot;   - /opt/MacOSX10.9.sdk  # [osx]&amp;quot; &amp;gt;&amp;gt; ~/conda_build_config.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;link-to-sdk-for-circle-ci-based-support-scripts&#34;&gt;Link to SDK for Circle CI based support scripts&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
ln -s /opt/MacOSX10.9.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;prepare-conda-environment&#34;&gt;Prepare Conda environment&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda create -n freecad_0_18_1 -y
conda activate freecad_0_18_1
conda config --add channels conda-forge
conda install conda-build -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;get-freecad-feedstock&#34;&gt;Get FreeCAD feedstock&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/conda-forge/freecad-feedstock
cd freecad-feedstock/
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;build-freecad&#34;&gt;Build FreeCAD&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda build ./recipe -m ./.ci_support/osx_python3.7.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: I found it wasn&amp;rsquo;t necessary to add &lt;code&gt;-D FREECAD_USE_3DCONNEXION=ON&lt;/code&gt; to &lt;code&gt;recipe/build.sh&lt;/code&gt; as the build seemed to pick up the
presence of the installed driver and use it by default.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: To modify the version of FreeCAD which is build, edit &lt;code&gt;recipe/meta.yaml&lt;/code&gt; and change the &lt;code&gt;version&lt;/code&gt; variable e.g.:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{% set version = &amp;quot;master&amp;quot; %}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;install-freecad&#34;&gt;Install FreeCAD&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;conda install -c file://${CONDA_PREFIX}/conda-bld/ freecad=0.18.1 -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: &lt;code&gt;conda install --use-local freecad=0.18.1&lt;/code&gt; didn&amp;rsquo;t seem to use the locally built package - possibly related to &lt;a href=&#34;https://github.com/conda/conda/issues/7024&#34;&gt;this reported issue&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;use-it&#34;&gt;Use it!&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;FreeCAD
&lt;/code&gt;&lt;/pre&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Home Lab Fit-Out</title>
            <link>https://vectronic.io/posts/home-lab-fit-out/</link>
            <pubDate>Mon, 21 Jan 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/home-lab-fit-out/</guid>
            <description>&lt;p&gt;I finished the DIY fit-out of my lab/office/study late last year.&lt;/p&gt;
&lt;p&gt;A lot of planning and design was done before I started cutting into flat-pack furniture with the circular saw.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m very pleased with the result. This is a good thing as I&amp;rsquo;ll be spending a significant portion of my life for the coming years here.&lt;/p&gt;
&lt;p&gt;The end result is pictured below and further work in progress shots are &lt;a href=&#34;https://www.pinterest.co.uk/vectronic/lab/&#34;&gt;posted on Pinterest&lt;/a&gt;.&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/home-lab-fit-out/images/end-result.jpg&#34; width=&#34;70%&#34;/&gt; &lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/design">design</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Legify 0.1.0</title>
            <link>https://vectronic.io/posts/legify-0.1.0/</link>
            <pubDate>Fri, 18 Jan 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/legify-0.1.0/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been developing a &lt;a href=&#34;https://www.freecadweb.org&#34;&gt;FreeCAD&lt;/a&gt; macro for a while with the following aims:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get to grips with FreeCAD and parametric modelling concepts: sketches, constraints, datum planes etc.&lt;/li&gt;
&lt;li&gt;Learn Python and use it for FreeCAD scripting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To really push the boundaries, I challenged myself to use Python scripting in conjunction with the PartDesign workbench: I wanted to end up with a parametric model fully based on sketches and datum planes.&lt;/p&gt;
&lt;p&gt;The latest macro code, brief overview and instructions are available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;https://github.com/vectronic/freecad-legify-macros&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The very first &lt;code&gt;v0.1.0&lt;/code&gt; cut is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.1.0&#34;&gt;https://github.com/vectronic/freecad-legify-macros/releases/tag/v0.1.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve learnt and discovered various things on this journey:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vectronic.io/posts/multi-file-macro-in-freecad/&#34;&gt;Multi-File Macro in FreeCAD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vectronic.io/posts/utf8-in-freecad/&#34;&gt;Unicode in FreeCAD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vectronic.io/posts/reloading-freecad-macro-code/&#34;&gt;Reloading FreeCAD Macro Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vectronic.io/posts/pycharm-for-freecad-macro-development/&#34;&gt;PyCharm for FreeCAD Macro Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vectronic.io/posts/freecad-part-design-indices/&#34;&gt;FreeCAD Part Design Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?f=8&amp;amp;t=24238&amp;amp;p=274418#p274418&#34;&gt;Issue with padding up to face&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example images below. Check it out and let me know what you think!&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/legify-0.1.0/images/parameters.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/legify-0.1.0/images/simple.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/legify-0.1.0/images/classic.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/legify-0.1.0/images/odd.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/legify-0.1.0/images/sketch.png&#34; width=&#34;50%&#34;/&gt; &lt;/figure&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/legify">legify</category>
            <category domain="https://vectronic.io/tags/python">python</category>
            <category domain="https://vectronic.io/tags/release">release</category>
            <category domain="https://vectronic.io/tags/freecad">freecad</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>FreeCAD Part Design Indices</title>
            <link>https://vectronic.io/posts/freecad-part-design-indices/</link>
            <pubDate>Sat, 05 Jan 2019 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/freecad-part-design-indices/</guid>
            <description>&lt;p&gt;There are several limitations when referencing items in FreeCAD via Python script. This includes needing to reference
Part items such as edges and faces by name, whilst the names are liable (and likely) to change each time the model is modified.&lt;/p&gt;
&lt;p&gt;There are also a number of exposed native methods in the Python scripting layer which expect (rarely documented)
integer based constants. In this post I collate what I&amp;rsquo;ve learnt about these constants for future reference.&lt;/p&gt;
&lt;h2 id=&#34;body-origin-axes-and-planes&#34;&gt;Body Origin Axes and Planes&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;Origin&lt;/em&gt; of a Part Design workbench &lt;em&gt;Body&lt;/em&gt; called &lt;code&gt;myBody&lt;/code&gt; can be acquired via:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;origin = App.getDocument(&amp;#39;Unnamed&amp;#39;).getObject(&amp;#39;myBody&amp;#39;).Origin
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The axes and planes for this &lt;em&gt;Origin&lt;/em&gt; are available as &lt;code&gt;OriginFeatures&lt;/code&gt; which can be identified as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;for feat in b.Origin.OriginFeatures:
	feat.Name
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which outputs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;#39;X_Axis&amp;#39;
&amp;#39;Y_Axis&amp;#39;
&amp;#39;Z_Axis&amp;#39;
&amp;#39;XY_Plane&amp;#39;
&amp;#39;XZ_Plane&amp;#39;
&amp;#39;YZ_Plane&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hence to get a reference to one of these you can iterate through &lt;code&gt;OriginFeatures&lt;/code&gt; matching against the desired feature &lt;code&gt;Name&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However if you want to live dangerously, you can rely on indexing into the array of &lt;code&gt;OriginFeatures&lt;/code&gt; with these values:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ORIGIN_X_AXIS_INDEX = 0
ORIGIN_Y_AXIS_INDEX = 1
ORIGIN_Z_AXIS_INDEX = 2
ORIGIN_XY_PLANE_INDEX = 3
ORIGIN_XZ_PLANE_INDEX = 4
ORIGIN_YZ_PLANE_INDEX = 5
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The risk here is that the native code layer &lt;code&gt;OriginFeatures&lt;/code&gt; array order may change between FreeCAD releases.&lt;/p&gt;
&lt;h2 id=&#34;sketch-geometry-and-constraints&#34;&gt;Sketch Geometry and Constraints&lt;/h2&gt;
&lt;h3 id=&#34;geometry-item-indices&#34;&gt;Geometry Item Indices&lt;/h3&gt;
&lt;p&gt;Special indices are defined as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Horizontal axis: -1&lt;/li&gt;
&lt;li&gt;Vertical axis: -2&lt;/li&gt;
&lt;li&gt;First external geometry construction item: -3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hence, external geometry constructions items in a sketch are indexed from -3 descending!&lt;/p&gt;
&lt;h3 id=&#34;vertex-indices&#34;&gt;Vertex Indices&lt;/h3&gt;
&lt;p&gt;The start vertex of a geometry line segment has index 1 and the end vertex has index 2.&lt;/p&gt;
&lt;p&gt;The centre vertex of a geometry circle is index 3.&lt;/p&gt;
&lt;h3 id=&#34;examples&#34;&gt;Examples&lt;/h3&gt;
&lt;p&gt;Creating an &lt;code&gt;DistanceX&lt;/code&gt; constraint between a line segment start and the origin point:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SKETCH_GEOMETRY_VERTEX_START_INDEX = 1
SKETCH_GEOMETRY_ITEM_HORIZONTAL_AXIS_INDEX = -1

my_constraint = Sketcher.Constraint(&amp;#34;DistanceX&amp;#34;,
                                    segment_index, SKETCH_GEOMETRY_VERTEX_START_INDEX,
                                    SKETCH_GEOMETRY_ITEM_HORIZONTAL_AXIS_INDEX, SKETCH_GEOMETRY_VERTEX_START_INDEX, 
                                    distance)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Creating a &lt;code&gt;PointOnObject&lt;/code&gt; constraint between a line segment start and an external item used as a geometry construction item:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SKETCH_GEOMETRY_VERTEX_START_INDEX = 1
SKETCH_GEOMETRY_FIRST_CONSTRUCTION_INDEX = -3

my_sketch.addExternal(my_datum_plane.Label, &amp;#39;&amp;#39;)
my_constraint = Sketcher.Constraint(&amp;#34;PointOnObject&amp;#34;, 
                                    segment_index, SKETCH_GEOMETRY_VERTEX_START_INDEX, 
                                    SKETCH_GEOMETRY_FIRST_CONSTRUCTION_INDEX)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Creating a &lt;code&gt;DistanceY&lt;/code&gt; constraint between the centre of a circle and the origin point:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SKETCH_GEOMETRY_VERTEX_START_INDEX = 1
SKETCH_GEOMETRY_VERTEX_CENTRE_INDEX = 3
SKETCH_GEOMETRY_ITEM_HORIZONTAL_AXIS_INDEX = -1

my_constraint = Sketcher.Constraint(&amp;#34;DistanceY&amp;#34;, 
                                    segment_index, SKETCH_GEOMETRY_VERTEX_CENTRE_INDEX, 
                                    SKETCH_GEOMETRY_ITEM_HORIZONTAL_AXIS_INDEX, SKETCH_GEOMETRY_VERTEX_START_INDEX, 
                                    distance)
&lt;/code&gt;&lt;/pre&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>PyCharm for FreeCAD Macro Development</title>
            <link>https://vectronic.io/posts/pycharm-for-freecad-macro-development/</link>
            <pubDate>Thu, 27 Dec 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/pycharm-for-freecad-macro-development/</guid>
            <description>&lt;p&gt;Beyond simple scripts, FreeCAD macro development really benefits from using a Python IDE. My Python IDE of choice is PyCharm.&lt;/p&gt;
&lt;p&gt;I have been able to setup the same Python environment with FreeCAD and PyCharm using this great project
&lt;a href=&#34;https://github.com/FreeCAD/FreeCAD_Conda&#34;&gt;https://github.com/FreeCAD/FreeCAD_Conda&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This allows the same Python syntax and semantics to be applied (especially important when switching from Python 2 to
Python 3). Unfortunately however, having code completion for FreeCAD modules still eludes me&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;The following steps will get PyCharm and FreeCAD using the same Python installation.&lt;/p&gt;
&lt;p&gt;NOTE: This was done on MacOS.&lt;/p&gt;
&lt;h4 id=&#34;install-miniconda&#34;&gt;Install Miniconda&lt;/h4&gt;
&lt;p&gt;Download Miniconda installer from &lt;a href=&#34;https://conda.io/miniconda.html&#34;&gt;https://conda.io/miniconda.html&lt;/a&gt; and install it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bash Miniconda3-latest-MacOSX-x86_64.sh 
echo &amp;quot;. /Users/vectronic/miniconda3/etc/profile.d/conda.sh&amp;quot; &amp;gt;&amp;gt; ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;create-conda-environment-for-freecad&#34;&gt;Create Conda Environment for FreeCAD&lt;/h4&gt;
&lt;p&gt;A Conda environment with FreeCAD can then be built with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conda create -n freecad-0.18-mac freecad
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;use-freecad&#34;&gt;Use FreeCAD&lt;/h4&gt;
&lt;p&gt;To use the FreeCAD binary built with Conda it needs to be launched from the terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conda activate freecad-0.18-mac
FreeCAD
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inside the FreeCAD Python console you can then check the Python environment using:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import sys
print(&#39;Python %s on %s&#39; % (sys.version, sys.platform))
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;use-conda-environment-in-pycharm&#34;&gt;Use Conda Environment in PyCharm&lt;/h4&gt;
&lt;p&gt;The same Conda environment can then be configured within your PyCharm project via the following GUI path:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PyCharm Preferences -&amp;gt; Project Interpreter -&amp;gt; Gear Icon -&amp;gt; Add -&amp;gt; Conda Environment -&amp;gt; Existing Environment
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Choose the location of the Python executable from the Conda environment. In my case this is &lt;code&gt;~/miniconda3/envs/freecad-0.18-mac/bin/python&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now from the PyCharm Python console you should get the same results as previously with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import sys
print(&#39;Python %s on %s&#39; % (sys.version, sys.platform))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;fail&#34;&gt;Fail&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Despite the above and my endless attempts to configure dynamic library and module paths correctly, code completion just
will not work. As far as I can tell it relates to an issue with how PyCharm handles processing of dynamic
native libraries.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t hold much hope of it being resolved:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://youtrack.jetbrains.com/issue/PY-20463&#34;&gt;https://youtrack.jetbrains.com/issue/PY-20463&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Reloading FreeCAD Macro Code</title>
            <link>https://vectronic.io/posts/reloading-freecad-macro-code/</link>
            <pubDate>Thu, 27 Dec 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/reloading-freecad-macro-code/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been developing a fairly complex macro for FreeCAD and wanted to re-run it after making code changes without
having to restart FreeCAD.&lt;/p&gt;
&lt;p&gt;I found this &lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?t=320&#34;&gt;forum posting&lt;/a&gt; which gave me the answer.&lt;/p&gt;
&lt;p&gt;This post was discussing reloading code for workbenches and GUI Commands (which has some
&lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?t=320#p2066&#34;&gt;caveats&lt;/a&gt;) and it also works perfectly for macros.&lt;/p&gt;
&lt;p&gt;I have a multi-file macro setup as discussed in &lt;a href=&#34;https://vectronic.io/posts/multi-file-macro-in-freecad/&#34;&gt;this post&lt;/a&gt;.
The entry point is a &lt;code&gt;.FCMacro&lt;/code&gt; file with the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;from Legify.Dialog import *
Dialog()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;From within the FreeCAD Python console, the macro dialog can be displayed for the first time with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from Legify import Dialog
&amp;gt;&amp;gt;&amp;gt; Dialog.Dialog()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To reload and redisplay the dialog when code has been modified:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;reload(Dialog); Dialog.Dialog()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you need to update sub-modules, they need to be reloaded (as well as the parent module loading them) e.g.:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from Legify import Brick; from Legify import Body
&amp;gt;&amp;gt;&amp;gt; reload(Body); reload(Brick); reload(Dialog); Dialog.Dialog()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;NOTE: If you are using Python 3, you will first need to import the &lt;code&gt;reload&lt;/code&gt; module:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;from importlib import reload
&lt;/code&gt;&lt;/pre&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Moderated Comments System on a Static HTML Website</title>
            <link>https://vectronic.io/posts/self-hosted-comments-on-a-hugo-website/</link>
            <pubDate>Mon, 10 Dec 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/self-hosted-comments-on-a-hugo-website/</guid>
            <description>&lt;p&gt;This website is built using &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt; and deployed on &lt;a href=&#34;https://www.netlify.com&#34;&gt;Netlify&lt;/a&gt;. I&amp;rsquo;ve been
very happy with both of these technologies since deciding to use them.
I did find the Hugo documentation somewhat impenetrable: all the information and detail is there,
but it&amp;rsquo;s a steep ol&amp;rsquo; curve for a newcomer. I&amp;rsquo;ve surmounted that curve and this site now features
statically hosted blog comments - including moderation functionality.&lt;/p&gt;
&lt;p&gt;This post aims to step through the required config and to point out some salient points.&lt;/p&gt;
&lt;p&gt;The general approach is inspired by the following article and accompanying sample project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://css-tricks.com/jamstack-comments/&#34;&gt;https://css-tricks.com/jamstack-comments/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/philhawksworth/jamstack-comments-engine&#34;&gt;https://github.com/philhawksworth/jamstack-comments-engine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The configured system uses Netlify Forms and Functions add-ons. Both of these are free for low volume usage.
Comment notification and moderation relies on Slack which is also free.&lt;/p&gt;
&lt;p&gt;The source and full configuration instructions are available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/website&#34;&gt;https://github.com/vectronic/website&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;integration-overview&#34;&gt;Integration Overview&lt;/h1&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/self-hosted-comments-on-a-hugo-website/images/integration-overview.png&#34; width=&#34;100%&#34;/&gt; &lt;/figure&gt;
&lt;h2 id=&#34;comment-submission&#34;&gt;Comment Submission&lt;/h2&gt;
&lt;p&gt;The following occurs when a user submits a comment via the comment form on a blog post page:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The form contents are posted to Netlify as the form has a &lt;code&gt;netlify&lt;/code&gt; attribute and stored in a Netlify table
called &lt;code&gt;pending-comments&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The insertion of a table entry triggers a Netlify Lambda function called &lt;code&gt;comment-submitted&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The Lambda function posts the comment data via the Slack API to a simple Slack App. My app is called &lt;code&gt;vectronic-comment&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The Slack App posts the comment to a Slack channel with user actions provided to either &amp;ldquo;delete&amp;rdquo;
or &amp;ldquo;approve&amp;rdquo; the comment. My channel is called &lt;code&gt;#vectronic-comment&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;comment-moderation&#34;&gt;Comment Moderation&lt;/h2&gt;
&lt;p&gt;The following occurs when a user action on a comment is clicked in the &lt;code&gt;#vectronic-comment&lt;/code&gt; channel:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The user action invokes a Netlify Lambda function called &lt;code&gt;comment-action&lt;/code&gt;.
&lt;ol&gt;
&lt;li&gt;If the action was &amp;ldquo;delete&amp;rdquo;, the function calls the Netlify API to delete the entry from the &lt;code&gt;pending-comments&lt;/code&gt; table.&lt;/li&gt;
&lt;li&gt;If the action was &amp;ldquo;approve&amp;rdquo;, the function calls the Netlify API to move the entry from the &lt;code&gt;pending-comments&lt;/code&gt; table to the &lt;code&gt;approved-comments&lt;/code&gt; table.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;approved-comment-publishing&#34;&gt;Approved Comment Publishing&lt;/h2&gt;
&lt;p&gt;Approved comments are rendered as static HTML as part of the Hugo site build. When a new comment is
added to the &lt;code&gt;approved-comments&lt;/code&gt; table the following occurs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The insertion of a table entry triggers a Netlify build via a Build Hook.&lt;/li&gt;
&lt;li&gt;The Netlify build runs a &lt;a href=&#34;https://gulpjs.com&#34;&gt;Gulp&lt;/a&gt; task which:
&lt;ol&gt;
&lt;li&gt;Uses the Netlify API to grab all of the approved comments from the &lt;code&gt;approved-comments&lt;/code&gt; table.&lt;/li&gt;
&lt;li&gt;The comments are placed in a map using the blog post as a key and written to a data file.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;The Netlify build then runs Hugo which uses the data file as a data source for each of the generated post pages.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;configuration&#34;&gt;Configuration&lt;/h1&gt;
&lt;p&gt;Presented below is a fairly terse outline of the configuration required in Slack and Netlify.&lt;/p&gt;
&lt;h2 id=&#34;slack&#34;&gt;Slack&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Configure a &lt;a href=&#34;https://api.slack.com/slack-apps&#34;&gt;Slack App&lt;/a&gt; for your workspace. Mine is called &lt;code&gt;vectronic-comment&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add an &lt;a href=&#34;https://api.slack.com/incoming-webhooks&#34;&gt;Incoming Webhook&lt;/a&gt; to the app which will post messages to a channel.
My channel is called &lt;code&gt;#vectronic-comment&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable &lt;a href=&#34;https://api.slack.com/interactive-messages&#34;&gt;Interactive messages&lt;/a&gt; on the app and configure a Request URL for the
actions which invokes the Netlify Lambda function called &lt;code&gt;comment-action&lt;/code&gt;. My URL looks like this (the shared secret is discussed further below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; https://vectronic.io/.netlify/functions/comment-action?VECTRONIC_FUNCTION_AUTH=&amp;lt;shared secret&amp;gt;     
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the app in your Slack workspace.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The above should allow posting comment details via the Slack API to a channel in your workspace. The comments
will appear as interactive messages with actions to click on. Clicking an action will post back to the configured
Netlify Function.&lt;/p&gt;
&lt;h2 id=&#34;netlify&#34;&gt;Netlify&lt;/h2&gt;
&lt;h3 id=&#34;one-time-only-table-creation&#34;&gt;One Time Only Table Creation&lt;/h3&gt;
&lt;p&gt;The Netlify tables that store data submitted from website forms are added to your website configuration upon the initial posting from a form. In our use case both forms
(&lt;code&gt;pending-comments&lt;/code&gt; and &lt;code&gt;approved-comments&lt;/code&gt;) need to exist before we can do any further configuration:&lt;/p&gt;
&lt;h4 id=&#34;pending-comments&#34;&gt;Pending Comments&lt;/h4&gt;
&lt;p&gt;For the &lt;code&gt;pending-comments&lt;/code&gt; table creation, just submit a test comment using your website comments form. Ensure the HTML
form has a name of &lt;code&gt;pending-comments&lt;/code&gt; and the attribute &lt;code&gt;netlify&lt;/code&gt; set.&lt;/p&gt;
&lt;p&gt;Once a test comment is posted, you should see a &lt;code&gt;pending-comments&lt;/code&gt;   table in the Netlify admin UI and will be able to configure notifications for it.&lt;/p&gt;
&lt;p&gt;Refer to my website source for this &lt;a href=&#34;https://github.com/vectronic/website/blob/master/src/themes/vectronic/layouts/partials/comments.html&#34;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;approved-comments&#34;&gt;Approved Comments&lt;/h4&gt;
&lt;p&gt;Entries in the &lt;code&gt;approved-comments&lt;/code&gt; form table are only added via Slack integration calls to the Netlify Lambda function &lt;code&gt;comment-action&lt;/code&gt;.
But again, this table needs to be created in Netlify first so that notifications can be configured for it.&lt;/p&gt;
&lt;p&gt;The easiest way to achieve this is to temporarily deploy a website page which contains an appropriate HTML form having a name of &lt;code&gt;approved-comments&lt;/code&gt; and the attribute &lt;code&gt;netlify&lt;/code&gt; set.&lt;/p&gt;
&lt;p&gt;Once a test comment is posted, you should see an &lt;code&gt;approved-comments&lt;/code&gt; table in the Netlify admin UI and will be able to configure notifications for it.
The &lt;code&gt;approved-comments&lt;/code&gt; HTML form can then be commented out or removed from your website source.&lt;/p&gt;
&lt;p&gt;Refer to my website source for this &lt;a href=&#34;https://github.com/vectronic/website/blob/master/src/themes/vectronic/layouts/partials/comments.html&#34;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;user-account-level-oauth-token&#34;&gt;User Account Level OAuth Token&lt;/h3&gt;
&lt;p&gt;At the user account level in Netlify, create a new OAuth application personal access token. Mine is called &lt;code&gt;vectronic-comments-management&lt;/code&gt;.
This Personal Access Token will be used when making calls to the Netlify API from Netlify Functions.&lt;/p&gt;
&lt;p&gt;The Netlify Personal Access Tokens configuration page can be found &lt;a href=&#34;https://app.netlify.com/account/applications&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;build-environment-variables&#34;&gt;Build Environment Variables&lt;/h3&gt;
&lt;p&gt;The following should be defined as environment variables for the Netlify build environment so that sensitive information
can be kept out of the website source:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;NETLIFY_API_AUTH&lt;/code&gt; - The personal access token created in the Netlify OAuth applications section.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;NETLIFY_APPROVED_COMMENTS_FORM_ID&lt;/code&gt; - The ID of the &lt;code&gt;approved-comments&lt;/code&gt; form table created in Netlify.
The value for this can be ascertained from the Netlify URL seen in the browser when navigating to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  Account -&amp;gt; Site -&amp;gt; Forms -&amp;gt; approved-comments.
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SLACK_COMMENT_WEBHOOK_URL&lt;/code&gt; - The incoming webhook URL provided for your Slack app when the Incoming Webhook was added to it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;VECTRONIC_FUNCTION_AUTH&lt;/code&gt; - This can be any shared secret key. It is used to prevent access to the publicly exposed Netlify Functions (more on this below).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above can be set in the &amp;ldquo;Continuous Deployment&amp;rdquo; settings section of the Netlify website admin UI.&lt;/p&gt;
&lt;h3 id=&#34;build-hooks&#34;&gt;Build Hooks&lt;/h3&gt;
&lt;p&gt;Define a Build Hook which will be used to automatically rebuild the site when a new comment is approved. Mine is called &lt;code&gt;build-vectronic&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The above can be set in the &amp;ldquo;Continuous Deployment&amp;rdquo; settings section of the Netlify website admin UI.&lt;/p&gt;
&lt;h3 id=&#34;form-notifications&#34;&gt;Form Notifications&lt;/h3&gt;
&lt;p&gt;Configure the following Outgoing Webhooks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;On a new form submission to the &lt;code&gt;pending-comments&lt;/code&gt; form, post to the &lt;code&gt;comment-submitted&lt;/code&gt; function configured in Netlify e.g.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://vectronic.netlify.com/.netlify/functions/comment-submitted?VECTRONIC_FUNCTION_AUTH=&#34;&gt;https://vectronic.netlify.com/.netlify/functions/comment-submitted?VECTRONIC_FUNCTION_AUTH=&lt;/a&gt;&lt;shared secret&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On a new form submission to the &lt;code&gt;approved-comments&lt;/code&gt; form, post to the build hook configured in Netlify.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above can be set in the &lt;code&gt;Form notification&lt;/code&gt; settings section for your Netlify website.&lt;/p&gt;
&lt;h1 id=&#34;implementation&#34;&gt;Implementation&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;Presented below are the salient points of implementation that work in conjunction with the above configuration.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;new-comment-form&#34;&gt;New Comment Form&lt;/h2&gt;
&lt;p&gt;The source for the website comment form &lt;code&gt;pending-comments&lt;/code&gt; can be seen &lt;a href=&#34;https://github.com/vectronic/website/blob/master/src/themes/vectronic/layouts/partials/comments.html&#34;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;
&lt;p&gt;A large part of the action occurs in the implementation of the two Netlify Lambda functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/vectronic/website/blob/master/src/functions/comment-submitted.js&#34;&gt;https://github.com/vectronic/website/blob/master/src/functions/comment-submitted.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/vectronic/website/blob/master/src/functions/comment-action.js&#34;&gt;https://github.com/vectronic/website/blob/master/src/functions/comment-action.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I believe these are fairly self-explanatory. If they&amp;rsquo;re not, post me a comment!&lt;/p&gt;
&lt;h2 id=&#34;approved-comments-gulp-task&#34;&gt;Approved Comments Gulp Task&lt;/h2&gt;
&lt;p&gt;The logic to pull approved comments data from the Netlify &lt;code&gt;approved-comments&lt;/code&gt; table is implemented in a Gulp task:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/vectronic/website/blob/master/gulpfile.js&#34;&gt;https://github.com/vectronic/website/blob/master/gulpfile.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I believe this is fairly self-explanatory. If not, post me a comment!&lt;/p&gt;
&lt;h2 id=&#34;hugo-site-build&#34;&gt;Hugo Site Build&lt;/h2&gt;
&lt;p&gt;Netlify is configured to build the Hugo site via a &lt;a href=&#34;https://github.com/vectronic/website/blob/master/netlify.toml&#34;&gt;netlify.toml&lt;/a&gt; file as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gulp build:comments &amp;amp;&amp;amp; hugo &amp;amp;&amp;amp; npx netlify-lambda build src/functions
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This build instruction performs three simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pull down the approved comments data into a map structure written to file&lt;/li&gt;
&lt;li&gt;Render the website reading data from the map file&lt;/li&gt;
&lt;li&gt;Build the Lambda functions&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;approved-comments-rendering&#34;&gt;Approved Comments Rendering&lt;/h2&gt;
&lt;p&gt;The source for the website rendering of approved comments can be seen &lt;a href=&#34;https://github.com/vectronic/website/blob/master/src/themes/vectronic/layouts/partials/comments.html&#34;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;
&lt;p&gt;The Netlify Lambda functions &lt;code&gt;comment-submitted&lt;/code&gt; and &lt;code&gt;comment-action&lt;/code&gt; are both available for invocation via public URLs. As I don&amp;rsquo;t
want anything apart from my website and my Slack account invoking them I have a simple shared secret check implemented:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// check auth
let queryStringParameters = event.queryStringParameters;
if (queryStringParameters[&amp;quot;VECTRONIC_FUNCTION_AUTH&amp;quot;] !== process.env.VECTRONIC_FUNCTION_AUTH) {
    return console.log(&amp;quot;VECTRONIC_FUNCTION_AUTH query param incorrect&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;a-quick-note-on-scale&#34;&gt;A Quick Note on Scale&lt;/h1&gt;
&lt;p&gt;I have previously read some criticisms of the approach described here with respect to its ability to scale e.g. many posts requiring
many website rebuilds, the time taken to rebuild, the need to moderate each and every comment etc. etc.
For me, with currently around 4 posts and 0 comments, its fair to say this isn&amp;rsquo;t a concern. I will be happy when it does become a concern!&lt;/p&gt;
&lt;p&gt;When it does become a concern and I embark on implementing a more scalable solution,
I&amp;rsquo;m happy to know I will have all of my comment data available: both in static rendered form and as raw data available via the Netlify API.&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/hugo">hugo</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            <category domain="https://vectronic.io/tags/netlify">netlify</category>
            <category domain="https://vectronic.io/tags/slack">slack</category>
            <category domain="https://vectronic.io/tags/website">website</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Automatic Google Analytics Outbound Link Tracking</title>
            <link>https://vectronic.io/posts/automatic-google-analytics-outbound-link-tracking/</link>
            <pubDate>Mon, 26 Nov 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/automatic-google-analytics-outbound-link-tracking/</guid>
            <description>&lt;p&gt;Google Analytics tracking of internal links within your own website is super-simple.
Tracking outbound links is slightly more involved. &lt;a href=&#34;https://support.google.com/analytics/answer/7478520?hl=en&#34;&gt;Google tells you how&lt;/a&gt;,
but this requires remembering to modify each outbound link&amp;rsquo;s &lt;code&gt;onclick&lt;/code&gt; event handler.&lt;/p&gt;
&lt;p&gt;The Google answer involves installing an &lt;code&gt;onclick&lt;/code&gt; event handler similar to the following for each outbound link:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://www.example.com&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;onclick&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;trackOutboundLink(&amp;#39;http://www.example.com&amp;#39;); return false;&amp;#34;&lt;/span&gt;&amp;gt;Check out example.com&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When writing blog entries I didn&amp;rsquo;t want to have to remember this everytime. My other requirement was a nice indicator
for the reader when links are external.&lt;/p&gt;
&lt;p&gt;After suitable perusing of stackoverflow, and some trial and error, I submit to you the following code which handles a few hiccups
I encountered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;local links might be specified as relative or absolute&lt;/li&gt;
&lt;li&gt;links might be defined with relative protocol i.e. &lt;code&gt;//www.example.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Google Analytics might be blocked or somehow disabled&lt;/li&gt;
&lt;li&gt;there might be an existing &lt;code&gt;onclick&lt;/code&gt; handler defined&lt;/li&gt;
&lt;li&gt;there might be an existing &lt;code&gt;rel&lt;/code&gt; attribute (see further below for it&amp;rsquo;s use in styling)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, onto the code:&lt;/p&gt;
&lt;p&gt;Firstly, in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element is the standard Google Analytics gtag.js setup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://www.googletagmanager.com/gtag/js?id=UA-121478710-1&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        window.&lt;span style=&#34;color:#a6e22e&#34;&gt;dataLayer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; window.&lt;span style=&#34;color:#a6e22e&#34;&gt;dataLayer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gtag&lt;/span&gt;(){&lt;span style=&#34;color:#a6e22e&#34;&gt;dataLayer&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;push&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;arguments&lt;/span&gt;);}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;gtag&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;js&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Date());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;gtag&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;config&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;UA-121478710-1&amp;#39;&lt;/span&gt;, { &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;anonymize_ip&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nextly, at the end of the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag is the automatic discovery, styling and &lt;code&gt;onclick&lt;/code&gt; hijacking of the outbound links:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Get all links on the page
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    Array.&lt;span style=&#34;color:#a6e22e&#34;&gt;from&lt;/span&gt;(document.&lt;span style=&#34;color:#a6e22e&#34;&gt;getElementsByTagName&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Filter for outbound links
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        .&lt;span style=&#34;color:#a6e22e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;link&lt;/span&gt; =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ((&lt;span style=&#34;color:#a6e22e&#34;&gt;link&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;indexOf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;location&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;host&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;link&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;indexOf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;location&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;host&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#a6e22e&#34;&gt;link&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;match&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;/^http:/i&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;link&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;match&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;/^https:/i&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;link&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;match&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;/^mailto:/i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// For each external link
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        .&lt;span style=&#34;color:#a6e22e&#34;&gt;forEach&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// Set rel attribute as external to ensure styling applied
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;rel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;rel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;rel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; external&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;rel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;external&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// Save old onclick handler (if it exists) and install new one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;oldOnClick&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;onclick&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;onclick&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;event&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// Test if Google Analytics loaded
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (window.&lt;span style=&#34;color:#a6e22e&#34;&gt;ga&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ga&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;create&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#75715e&#34;&gt;// Send tracking event
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#a6e22e&#34;&gt;gtag&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;event&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;event_category&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;outbound&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;event_label&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;transport_type&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;beacon&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;event_callback&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            document.&lt;span style=&#34;color:#a6e22e&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    document.&lt;span style=&#34;color:#a6e22e&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;externalLink&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// Invoke replaced onclick handler if it existed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;oldOnClick&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;oldOnClick&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;call&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;event&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;P.S. For the styling of external links something like the following CSS-fu should work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[*|&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;rel&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;~=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;external&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;::&lt;span style=&#34;color:#a6e22e&#34;&gt;after&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;inline-block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;font-style&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;normal&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;font-variant&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;normal&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    text-rendering: &lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;-webkit-&lt;/span&gt;font-smoothing: antialiased;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;font-size&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;x-small&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;font-family&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Font Awesome 5 Free&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;content&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\f35d&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;padding-left&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.5&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/website">website</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Multi-File Macro in FreeCAD</title>
            <link>https://vectronic.io/posts/multi-file-macro-in-freecad/</link>
            <pubDate>Mon, 12 Nov 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/multi-file-macro-in-freecad/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been developing a fairly complex macro for FreeCAD and wanted to split the code out into a module with separate
files.&lt;/p&gt;
&lt;p&gt;I couldn&amp;rsquo;t find instructions how to do this anywhere, but thankfully someone on the very helpful forum FreeCAD Forum
gave me &lt;a href=&#34;https://forum.freecadweb.org/viewtopic.php?t=26982&#34;&gt;this answer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So now I have the following in my macro folder:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Legify&lt;/code&gt; a sub-folder containing the Python module source files&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;legify-brick.FCMacro&lt;/code&gt; a macro file importing the module as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;from Legify import Brick
Brick.Dialog()
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This structure can be seen in the &lt;a href=&#34;https://github.com/vectronic/freecad-legify-macros&#34;&gt;macro repository on GitHub&lt;/a&gt;&lt;/p&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Unicode in FreeCAD</title>
            <link>https://vectronic.io/posts/utf8-in-freecad/</link>
            <pubDate>Wed, 03 Oct 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/utf8-in-freecad/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been writing a Python macro for FreeCAD as a learning exercise on both subjects. I thought it would be nice to
display the &lt;a href=&#34;https://www.fileformat.info/info/unicode/char/1f6c8/index.htm&#34;&gt;Circled Information Source&lt;/a&gt; unicode character
as a tooltip icon in a GUI form. It looks like this: 🛈 (if your current viewing font supports it).&lt;/p&gt;
&lt;p&gt;After attempting this for a couple of hours, I wanted to stop learning Python and head back to Java&amp;hellip;&lt;/p&gt;
&lt;p&gt;Here are the things to look out for when using Python 2.7:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;As per &lt;a href=&#34;https://www.python.org/dev/peps/pep-0263/&#34;&gt;PEP 263&lt;/a&gt; a Python source file needs to start with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# coding: UTF-8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This isn&amp;rsquo;t required in Python 3 as UTF-8 is the default encoding as per &lt;a href=&#34;https://www.python.org/dev/peps/pep-3120/&#34;&gt;PEP 3120&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UTF-8 &lt;a href=&#34;https://docs.python.org/2/reference/lexical_analysis.html#grammar-token-stringprefix&#34;&gt;string literals&lt;/a&gt; need
to be prefixed with a &lt;code&gt;u&lt;/code&gt; as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;u&amp;#34;My UTF-8 string 🛈&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure to use a unicode character which has a code point less than the
&lt;a href=&#34;https://docs.python.org/2/library/sys.html#sys.maxunicode&#34;&gt;sys.maxunicode&lt;/a&gt; for your build of Python!
This one was a real doozie to uncover. Here are some other devs &lt;a href=&#34;https://stackoverflow.com/a/1446456&#34;&gt;dealing with the same issue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Again things change in Python 3.3 as per &lt;a href=&#34;https://www.python.org/dev/peps/pep-0393/&#34;&gt;PEP 393&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Within the FreeCAD 18.0 Python terminal:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Python 2.7.15 (default, Aug 22 2018, 16:41:11) 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Type &amp;#39;help&amp;#39;, &amp;#39;copyright&amp;#39;, &amp;#39;credits&amp;#39; or &amp;#39;license&amp;#39; for more information.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; App.setActiveDocument(&amp;#34;Unnamed&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; App.ActiveDocument=App.getDocument(&amp;#34;Unnamed&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; Gui.ActiveDocument=Gui.getDocument(&amp;#34;Unnamed&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; import sys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; print sys.maxunicode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;65535
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course 🛈 has a decimal value of 128712 which is TOO BIG! So I&amp;rsquo;ve settled on using the
&lt;a href=&#34;https://www.fileformat.info/info/unicode/char/2139/index.htm&#34;&gt;Information Source&lt;/a&gt; character ℹ
which has a decimal value of 8505.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author><category domain="https://vectronic.io/tags/freecad">freecad</category>
            <category domain="https://vectronic.io/tags/tip">tip</category>
            <category domain="https://vectronic.io/tags/python">python</category>
            
        </item>
        
        <image>
            <url>https://vectronic.io/assets/img/icon.png</url>
            <title>vectronic</title>
            <link>https://vectronic.io/</link>
            <width>144</width>
            <height>144</height>
        </image>
        <item>
            <title>Sample Content</title>
            <link>https://vectronic.io/posts/sample-content/</link>
            <pubDate>Mon, 24 Sep 2018 00:00:00 +0000</pubDate>
            <guid>https://vectronic.io/posts/sample-content/</guid>
            <description>&lt;p&gt;Here is an image:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/sample-content/images/screenshot1.png&#34; alt=&#34;This is a caption&#34; width=&#34;60%&#34;/&gt; &lt;figcaption&gt;
    
    &lt;p&gt;
    This is a caption
    
    
    &lt;/p&gt;
    
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I ❤️ emoji!&lt;/p&gt;
&lt;h1 id=&#34;heading-level-1&#34;&gt;Heading Level 1&lt;/h1&gt;
&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non neque odio.&lt;/p&gt;
&lt;p&gt;Curabitur quis est ullamcorper, eleifend nisi a, rutrum eros. Donec laoreet quam massa, quis pellentesque odio ultrices nec. Nulla non mauris magna. Nullam ut enim ultrices, suscipit nunc in, suscipit tortor. Etiam lectus tortor, ultrices quis ligula nec, fermentum scelerisque velit. Sed accumsan, metus vel vestibulum rhoncus, nunc est sodales massa, facilisis sodales lacus turpis eu diam.&lt;/p&gt;
&lt;h2 id=&#34;heading-level-2&#34;&gt;Heading Level 2&lt;/h2&gt;
&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non neque odio. Curabitur quis est ullamcorper, eleifend nisi a, rutrum eros. Donec laoreet quam massa, quis pellentesque odio ultrices nec. Nulla non mauris magna. Nullam ut enim ultrices, suscipit nunc in, suscipit tortor. Etiam lectus tortor, ultrices quis ligula nec, fermentum scelerisque velit. Sed accumsan, metus vel vestibulum rhoncus, nunc est sodales massa, facilisis sodales lacus turpis eu diam.&lt;/p&gt;
&lt;h3 id=&#34;heading-level-3&#34;&gt;Heading Level 3&lt;/h3&gt;
&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non neque odio. Curabitur quis est ullamcorper, eleifend nisi a, rutrum eros. Donec laoreet quam massa, quis pellentesque odio ultrices nec. Nulla non mauris magna. Nullam ut enim ultrices, suscipit nunc in, suscipit tortor. Etiam lectus tortor, ultrices quis ligula nec, fermentum scelerisque velit. Sed accumsan, metus vel vestibulum rhoncus, nunc est sodales massa, facilisis sodales lacus turpis eu diam.&lt;/p&gt;
&lt;p&gt;Here is another image:&lt;/p&gt;

&lt;figure&gt;

&lt;img src=&#34;https://vectronic.io/posts/sample-content/images/screenshot2.png&#34; width=&#34;70%&#34;/&gt; &lt;/figure&gt;
&lt;p&gt;Here is a list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;
&lt;li&gt;Phasellus non neque odio. Curabitur quis est ullamcorper, eleifend nisi a, rutrum eros.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can use the mark tag to &lt;mark&gt;highlight&lt;/mark&gt; text.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;This line of text is meant to be treated as deleted text.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;This line of text will render as underlined&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;This line of text is meant to be treated as fine print.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This line rendered as bold text.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This line rendered as italicized text.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And here is &lt;code&gt;some inline code&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The following is a block quote:&lt;/p&gt;
&lt;blockquote class=&#34;blockquote&#34;&gt;
  &lt;p class=&#34;mb-0&#34;&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.&lt;/p&gt;
  &lt;footer class=&#34;blockquote-footer&#34;&gt;Someone famous in &lt;cite title=&#34;Source Title&#34;&gt;Source Title&lt;/cite&gt;&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;p&gt;The following is a lead text paragraph:&lt;/p&gt;
&lt;p class=&#34;lead&#34;&gt;
  Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.
&lt;/p&gt;
&lt;p&gt;Here is a block of code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;front_tube_ribs_sketch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;addExternal(self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;doc&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;top_inside_datum_plane&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Label, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;constraints&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(Sketcher&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Constraint(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PointOnObject&amp;#34;&lt;/span&gt;, segment_count &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
            <author>hello.vectronic@gmail.com (vectronic)</author>
        </item>
        
    </channel>
</rss>
