<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Samy Fodil</title>
    <description>The latest articles on DEV Community by Samy Fodil (@samyfodil).</description>
    <link>https://dev.to/samyfodil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1169977%2Fccc6f84f-692b-4930-b611-6bf54001d776.png</url>
      <title>DEV Community: Samy Fodil</title>
      <link>https://dev.to/samyfodil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samyfodil"/>
    <language>en</language>
    <item>
      <title>Building a Serverless Web Game With WebAssembly and Three.js</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Wed, 03 Sep 2025 13:51:12 +0000</pubDate>
      <link>https://dev.to/samyfodil/building-a-serverless-web-game-with-webassembly-and-threejs-3mbl</link>
      <guid>https://dev.to/samyfodil/building-a-serverless-web-game-with-webassembly-and-threejs-3mbl</guid>
      <description>&lt;p&gt;In this tutorial, we'll build an online &lt;strong&gt;tower stacking game&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 Try the final result: &lt;a href="https://taubyte.github.io/tower-blocks-game/" rel="noopener noreferrer"&gt;Play Now&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswjtae8pfg3ijnt39xzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswjtae8pfg3ijnt39xzd.png" alt="Taubyte - live demo" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Three.js + TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Go serverless functions on Taubyte&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Dev:&lt;/strong&gt; Dream (Taubyte's local cloud) + GitHub integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚡ Step 1: Run the Frontend Locally
&lt;/h2&gt;

&lt;p&gt;Clone and run the game — at this stage, it has &lt;strong&gt;no leaderboard&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/taubyte/example-games-tower-blocks.git
&lt;span class="nb"&gt;cd &lt;/span&gt;example-games-tower-blocks

npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9cxxlmunwo2e4x1wikh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9cxxlmunwo2e4x1wikh.png" alt="Taubyte - npm install npm run dev" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;http://localhost:3000&lt;/code&gt; — the game works, but scores aren't saved anywhere yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgiz8o3x2krx9fx1dko45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgiz8o3x2krx9fx1dko45.png" alt="Taubyte - local game test" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Step 2: Start Taubyte Local Cloud (Dream)
&lt;/h2&gt;

&lt;p&gt;Install Dream and start a local cloud instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @taubyte/dream
dream new multiverse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep this terminal open — it runs your local Taubyte cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq87wjfg6ze90ycocgz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq87wjfg6ze90ycocgz4.png" alt="Taubyte - new local cloud" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Step 3: Connect to Console
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://console.taubyte.com" rel="noopener noreferrer"&gt;console.taubyte.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Log in with your email and GitHub&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2escg2hu6b184hog47dl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2escg2hu6b184hog47dl.png" alt="Taubyte - login" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;From the dropdown, select &lt;strong&gt;Dream/blackhole&lt;/strong&gt; (your local cloud).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr4ki11tfzwku1wxfm87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr4ki11tfzwku1wxfm87.png" alt="Taubyte - login" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🖥️ Step 4: Create Applications
&lt;/h2&gt;

&lt;p&gt;Create and open a new project , this will create a code and a config repositories to save your project's data .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftf46wybowp2yhjg14hk9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftf46wybowp2yhjg14hk9.png" alt="Taubyte - Applications" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll need &lt;strong&gt;two apps&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;frontend&lt;/code&gt; → hosts the website&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backend&lt;/code&gt; → handles leaderboard logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feunmb1jhojfi2edp1d7f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feunmb1jhojfi2edp1d7f.png" alt="Taubyte - Applications" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Inside &lt;code&gt;frontend&lt;/code&gt; app, add a &lt;strong&gt;Website resource&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;tower_game&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Repo: pick your GitHub fork (console fetches repos automatically)&lt;/li&gt;
&lt;li&gt;Domain: use the default generated domain&lt;/li&gt;
&lt;li&gt;Path: &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthi9bogwhosuaentaidd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthi9bogwhosuaentaidd.png" alt="Taubyte - Website" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push configuration to GitHub (green &lt;strong&gt;Push&lt;/strong&gt; button).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lbj9uroul134p5z6l7f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lbj9uroul134p5z6l7f.png" alt="Taubyte - push button" width="248" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In another terminal, trigger builds:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dream inject push-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1f0ew7jyjjagjqhhed7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1f0ew7jyjjagjqhhed7.png" alt="Taubyte - dream inject push-all" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;trigger a build for the website specifically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dream inject push-specific &lt;span class="nt"&gt;--rid&lt;/span&gt; &amp;lt;ID&amp;gt; &lt;span class="nt"&gt;--fn&lt;/span&gt; &amp;lt;FULL_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27zrb1thvngr1fqcp16n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27zrb1thvngr1fqcp16n.png" alt="Taubyte - id and fullname" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find &lt;code&gt;rid&lt;/code&gt; and &lt;code&gt;full_name&lt;/code&gt; in the &lt;strong&gt;YAML tab&lt;/strong&gt; of the resource.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F072sru5vo998rso44cc9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F072sru5vo998rso44cc9.png" alt="Taubyte - Yaml" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add your Dream domain to &lt;code&gt;/etc/hosts&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1 your-domain.blackhole.localtau
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7b5pmkcj6t53uvb9cing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7b5pmkcj6t53uvb9cing.png" alt="Taubyte - " width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the console, click the ⚡ button on the website resource → frontend should now load locally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrrkmrpn0yugl433upt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrrkmrpn0yugl433upt4.png" alt="Taubyte - " width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkus5ikylh45gxj6lskzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkus5ikylh45gxj6lskzh.png" alt="Taubyte - " width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗄️ Step 5: Implement Backend
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create Database
&lt;/h3&gt;

&lt;p&gt;Inside &lt;code&gt;backend&lt;/code&gt; app, add a &lt;strong&gt;Database resource&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;leaderboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Matcher: &lt;code&gt;/leaderboard&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3us2ntuzjwhfnshhzi6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3us2ntuzjwhfnshhzi6.png" alt="Taubyte - database" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Library
&lt;/h3&gt;

&lt;p&gt;Add a &lt;strong&gt;Library&lt;/strong&gt; resource:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;api_leaderboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Language: Go (empty template)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this reference implementation:&lt;br&gt;
&lt;a href="https://github.com/taubyte/example-games-tower-blocks-backend" rel="noopener noreferrer"&gt;The Library's Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdewhg1j94i1rtqfx50m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdewhg1j94i1rtqfx50m.png" alt="Taubyte - library" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvq8rbani0r0psrabijd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvq8rbani0r0psrabijd.png" alt="Taubyte - library repo" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Functions
&lt;/h3&gt;

&lt;p&gt;In the &lt;strong&gt;Functions&lt;/strong&gt; tab, create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;getAll&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method: &lt;code&gt;GET&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Path: &lt;code&gt;/api/leaderboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Entry: &lt;code&gt;getAll&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjukq8cw2x2aijgkcbggy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjukq8cw2x2aijgkcbggy.png" alt="Taubyte - function" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;get&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method: &lt;code&gt;GET&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Path: &lt;code&gt;/api/score&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Query param: &lt;code&gt;player_name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Entry: &lt;code&gt;get&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg68rbalncqjrl7sfw47g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg68rbalncqjrl7sfw47g.png" alt="Taubyte - function" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;set&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method: &lt;code&gt;POST&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Path: &lt;code&gt;/api/score&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Entry: &lt;code&gt;set&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5o8sc8xu6g9ixmfvqt0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5o8sc8xu6g9ixmfvqt0.png" alt="Taubyte - function" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Step 6: Deploy and Test
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Push builds:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dream inject push-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Use &lt;code&gt;push-specific&lt;/code&gt; for just the library if needed.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wait for builds to complete in the &lt;strong&gt;Builds tab&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
&lt;li&gt;Test each function by clicking the ⚡ button in the console → you'll see live responses.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhxj0g6gioazhqaj7hr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhxj0g6gioazhqaj7hr1.png" alt="Taubyte - lightning function" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🌍 Step 7: Push to Production
&lt;/h2&gt;

&lt;p&gt;All that is left now is to push to production.&lt;br&gt;&lt;br&gt;
It's a really simple process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Log out&lt;/strong&gt; of the local cloud's console.&lt;/li&gt;
&lt;li&gt;Make sure you already have a &lt;strong&gt;Taubyte cloud online&lt;/strong&gt; set up.&lt;/li&gt;
&lt;li&gt;Log in using your &lt;strong&gt;email and domain name&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Instead of creating a project like we did the first time, &lt;strong&gt;import the local project from GitHub&lt;/strong&gt;.
Select it from the dropdown and click &lt;strong&gt;Import&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
&lt;li&gt;Open the imported project.
Change the applications' local generated domain to a production one by toggling &lt;strong&gt;Generate Domain&lt;/strong&gt;.
Do this for both &lt;strong&gt;frontend&lt;/strong&gt; and &lt;strong&gt;backend&lt;/strong&gt; apps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgds4j2zy1ztml98dx200.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgds4j2zy1ztml98dx200.png" alt="Taubyte - generate domain" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push your changes → this will trigger a &lt;strong&gt;config build&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
&lt;li&gt;If your project has a &lt;strong&gt;Library&lt;/strong&gt; or &lt;strong&gt;Website&lt;/strong&gt;, you must register the resource with Auth before builds work.
This can be done from the web console using the &lt;strong&gt;broken heart icon&lt;/strong&gt; 💔 next to the resource.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Opening your game now in the production domain should work properly with all features up and running 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Summary
&lt;/h2&gt;

&lt;p&gt;You now have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A frontend game hosted via Taubyte&lt;/li&gt;
&lt;li&gt;A backend with a database + Go library&lt;/li&gt;
&lt;li&gt;Three serverless functions powering a leaderboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All running locally with &lt;strong&gt;Dream&lt;/strong&gt;, and ready to deploy globally once you push to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Game Repository:&lt;/strong&gt; &lt;a href="https://github.com/taubyte/example-games-tower-blocks" rel="noopener noreferrer"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend Library:&lt;/strong&gt; &lt;a href="https://github.com/taubyte/example-games-tower-blocks-backend" rel="noopener noreferrer"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dream NPM Package:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@taubyte/dream" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Taubyte Documentation:&lt;/strong&gt; &lt;a href="https://tau.how" rel="noopener noreferrer"&gt;tau.how&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>webassembly</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Your Software, Your Cloud: Building Your Own Vercel Ain't That Hard!</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Wed, 23 Jul 2025 20:49:34 +0000</pubDate>
      <link>https://dev.to/samyfodil/your-software-your-cloud-building-your-own-vercel-aint-that-hard-2dbg</link>
      <guid>https://dev.to/samyfodil/your-software-your-cloud-building-your-own-vercel-aint-that-hard-2dbg</guid>
      <description>&lt;p&gt;&lt;em&gt;Why pay Vercel when you can build better? This is a guide to creating your own distributed cloud that rivals the big players—for a fraction of the cost.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At Taubyte, we’ve spent the last few of years building an open-source cloud platform. This guide is here to help you deploy it manually, step-by-step. It's a solid walkthrough to get a working, self-hosted Tau setup running across multiple continents.&lt;/p&gt;

&lt;p&gt;You'll build a globally distributed developer cloud with DNS-based load balancing, service discovery, and container orchestration—all with transparency and control, and with no vendor lock-in.&lt;/p&gt;

&lt;p&gt;And by the way, if you'd rather watch a video:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/QrLiJFK76og"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You're Building (And Why It's Awesome)
&lt;/h2&gt;

&lt;p&gt;We're not just spinning up a few servers here. You're building a genuinely distributed cloud platform. This platform will feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Global Edge Presence&lt;/strong&gt;: Deploy across multiple continents for maximum performance and redundancy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Downtime Deployments&lt;/strong&gt;: Built-in redundancy means your applications stay online.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS-Based Load Balancing&lt;/strong&gt;: No expensive, dedicated load balancers needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Service Discovery&lt;/strong&gt;: Your services find each other like magic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it as your personal Vercel, but one that you actually understand and control completely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwa0dkbwjdy6x0x5awe5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwa0dkbwjdy6x0x5awe5.png" alt="Your Own Cloud"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;A Fully Qualified Domain Name (FQDN)&lt;/strong&gt;: This guide uses &lt;code&gt;k8s.cyou&lt;/code&gt; as an example.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Advanced DNS Management&lt;/strong&gt;: Your DNS provider must support custom &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;NS&lt;/code&gt; records.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Infrastructure Plan
&lt;/h2&gt;

&lt;p&gt;We will deploy across three continents for performance and redundancy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;host-001-spain&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;host-002-uae&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;host-003-algeria&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Choose your hosting providers strategically. I recommend different providers in each region to avoid correlated failures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Host Preparation (Repeat on all nodes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Firewall Configuration
&lt;/h3&gt;

&lt;p&gt;First, ensure SSH access is not blocked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, open the necessary ports for Taubyte services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Peer-to-Peer Communication&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 4242,4247,4252/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web &amp;amp; DNS Traffic&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 80,443/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 53,953/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 53,953/udp
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Port &lt;code&gt;53&lt;/code&gt; handles public DNS queries, while &lt;code&gt;953&lt;/code&gt; is used for secure DNS control plane operations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enable Firewall&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable
sudo &lt;/span&gt;ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Install Tools &amp;amp; Free DNS Port
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl nano
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure &lt;code&gt;systemd-resolved&lt;/code&gt; to use a public DNS resolver and free up port 53 for Taubyte.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/resolved.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the following values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;DNS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1.1.1.1&lt;/span&gt;
&lt;span class="py"&gt;DNSStubListener&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why these specific changes matter&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare DNS (1.1.1.1)&lt;/strong&gt;: A fast, privacy-focused public DNS resolver with excellent uptime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNSStubListener=no&lt;/strong&gt;: Prevents conflicts with Seer service, which needs direct control over DNS resolution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apply the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-resolved.service
&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-sf&lt;/span&gt; /run/systemd/resolve/resolv.conf /etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Install Docker
&lt;/h3&gt;

&lt;p&gt;Docker is used as a containerization engine by tau.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://get.docker.com | sh
docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Install Tau
&lt;/h3&gt;

&lt;p&gt;Tau is the core of Taubyte's Developer Cloud Platform Solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://get.tau.link/tau | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Primary Node Configuration (Run on node 1 only)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Generate Master Configuration
&lt;/h3&gt;

&lt;p&gt;Get your node's public IP address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl ifconfig.me &lt;span class="nt"&gt;-4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate the configuration that defines your cloud. This node will enable all core services and initiate Docker's clustering mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tau config generate &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; k8s.cyou &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-s&lt;/span&gt; compute &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--services&lt;/span&gt; all &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ip&lt;/span&gt; YOUR_PUBLIC_IP &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dv&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--swarm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Understanding Taubyte's Service Architecture
&lt;/h3&gt;

&lt;p&gt;Your cloud runs on these core services, each with a specific purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Service&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Why You Need It&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Authentication &amp;amp; Authorization&lt;/td&gt;
&lt;td&gt;Secures access to your cloud APIs and resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Patrick&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CI/CD Orchestration&lt;/td&gt;
&lt;td&gt;Manages code builds and deployments automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monkey&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Job Execution Engine&lt;/td&gt;
&lt;td&gt;Runs the actual work (builds, functions, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TNS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Taubyte Naming Service&lt;/td&gt;
&lt;td&gt;Service registry and discovery system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hoarder&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Object Storage&lt;/td&gt;
&lt;td&gt;Handles file storage, backups, and static assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Seer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DNS Load Balancing&lt;/td&gt;
&lt;td&gt;Intelligent traffic distribution via DNS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Substrate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Event Processing&lt;/td&gt;
&lt;td&gt;The compute engine for serverless functions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Fine-Tuning Your Configuration (Optional)
&lt;/h3&gt;

&lt;p&gt;You can customize your setup by editing the generated configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /tb/config/compute.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Validate and Launch
&lt;/h3&gt;

&lt;p&gt;Always validate before proceeding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tau conf validate &lt;span class="nt"&gt;-s&lt;/span&gt; compute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful validation will output a unique cryptographic ID for your node. Now, launch the services manually to test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tau start &lt;span class="nt"&gt;-s&lt;/span&gt; compute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the logs scroll by, you are witnessing a distributed system come alive as services start and discover each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Test Your Cloud Node
&lt;/h3&gt;

&lt;p&gt;Before moving on, verify the node is working. Use a DNS lookup tool to query your node directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# dig &amp;lt;domain&amp;gt; @&amp;lt;nameserver&amp;gt;&lt;/span&gt;
dig seer.tau.k8s.cyou @YOUR_NODE_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get your node's IP back in the &lt;code&gt;ANSWER SECTION&lt;/code&gt;, your first node is live and responding correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making it Production-Ready with Systemd
&lt;/h2&gt;

&lt;p&gt;Running manually is great for testing, but production demands reliability. &lt;code&gt;systemd&lt;/code&gt; provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic restarts&lt;/strong&gt;: Services restart instantly after crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boot-time startup&lt;/strong&gt;: Your cloud survives server reboots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized logging&lt;/strong&gt;: Integrated logs via &lt;code&gt;journald&lt;/code&gt; for easier debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, stop the manual process with &lt;code&gt;Ctrl+C&lt;/code&gt;. Then, create the service file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /lib/systemd/system/tau@.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Tau %I&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;
&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;span class="py"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/tau start -s %i&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;
&lt;span class="py"&gt;LimitNOFILE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;16384&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable and start the service on your primary node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;tau@compute.service
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start tau@compute.service
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status tau@compute.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for "active (running)" to confirm success.&lt;/p&gt;




&lt;h2&gt;
  
  
  DNS Configuration
&lt;/h2&gt;

&lt;p&gt;Configure your domain's DNS records to delegate traffic to &lt;code&gt;Seer&lt;/code&gt; service for load balancing.&lt;/p&gt;

&lt;p&gt;At your domain provider, create the following records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Record&lt;/strong&gt; (for now, just the first node):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: A
Name: seer
Value: YOUR_NODE_1_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;NS Record&lt;/strong&gt; (delegation):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: NS  
Name: tau
Value: seer.k8s.cyou.
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;The trailing dot is required.&lt;/strong&gt; This delegates the &lt;code&gt;tau&lt;/code&gt; subdomain to your platform.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DNS Verification
&lt;/h3&gt;

&lt;p&gt;Test that your cloud is discoverable via public DNS using a tool like &lt;code&gt;dig&lt;/code&gt; or an online equivalent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig tns.tau.k8s.cyou @8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success returns your node's IP, proving public DNS is working.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scaling: Adding More Nodes (Run on nodes 2, 3...)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Export &amp;amp; Prepare Configuration
&lt;/h3&gt;

&lt;p&gt;On your &lt;strong&gt;primary node&lt;/strong&gt;, export the shared cluster configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Node 1&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;tau config &lt;span class="nb"&gt;export&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the YAML output. On your &lt;strong&gt;second node&lt;/strong&gt;, paste this into a new file: &lt;code&gt;compute.tmpl.yaml&lt;/code&gt;. Then, edit the file and &lt;strong&gt;remove the &lt;code&gt;location&lt;/code&gt; section&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Join the Cluster
&lt;/h3&gt;

&lt;p&gt;Get the multiaddress from your primary node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Node 1&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;tau config show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the public IP of your new node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Node 2&lt;/span&gt;
curl ifconfig.me &lt;span class="nt"&gt;-4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the &lt;strong&gt;new node&lt;/strong&gt;, generate its final configuration. This command uses the node's IP, the config template from the first node, and the first node's multiaddress to join the cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Node 2&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;tau config gen &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ip&lt;/span&gt; SECOND_NODE_IP &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--use&lt;/span&gt; compute.tmpl.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bootstrap&lt;/span&gt; FIRST_NODE_MULTIADDRESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Start the Service
&lt;/h3&gt;

&lt;p&gt;Set up and start the same &lt;code&gt;systemd&lt;/code&gt; service on the new node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Node 2&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;tau@compute.service
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start tau@compute.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Repeat this scaling process for all remaining nodes.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Last touches
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Update DNS Records
&lt;/h3&gt;

&lt;p&gt;Go back to your domain provider and add &lt;code&gt;A&lt;/code&gt; records for &lt;code&gt;seer&lt;/code&gt; pointing to &lt;strong&gt;all&lt;/strong&gt; your node IPs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seer IN A &amp;lt;host-001-spain IP&amp;gt;
seer IN A &amp;lt;host-002-uae IP&amp;gt;
seer IN A &amp;lt;host-003-algeria IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your DNS provider will now perform round-robin load balancing for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ensure Bootstrapping Persistence
&lt;/h3&gt;

&lt;p&gt;For a fully functional cluster that can recover from a full shutdown, every node must have a persistent list of its peers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Collect the multiaddress from &lt;strong&gt;all&lt;/strong&gt; nodes with &lt;code&gt;sudo tau config show&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; On &lt;strong&gt;each node&lt;/strong&gt;, edit &lt;code&gt;/tb/config/compute.yaml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Add all collected multiaddresses to the &lt;code&gt;peers&lt;/code&gt; list under the &lt;code&gt;p2p&lt;/code&gt; section.&lt;/li&gt;
&lt;li&gt; Restart the service on each node to apply the changes: &lt;code&gt;sudo systemctl restart tau@compute.service&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Global Load Balancing Verification
&lt;/h3&gt;

&lt;p&gt;Test your global setup. You should see all node IPs in the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig tns.tau.k8s.cyou
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Grand Test: Deploying Your First Application
&lt;/h2&gt;

&lt;p&gt;Time to see your cloud in action by deploying a real application.  Find detailed steps here: &lt;a href="https://tau.how/02-platform-getting-started/12-try-the-cloud/" rel="noopener noreferrer"&gt;https://tau.how/02-platform-getting-started/12-try-the-cloud/&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing Taubyte Console
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;code&gt;console.taubyte.com&lt;/code&gt; and enter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email&lt;/strong&gt;: Your email address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: Your domain (e.g., &lt;code&gt;k8s.cyou&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the console accepts your domain, your nodes are properly configured and discoverable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Creation
&lt;/h3&gt;

&lt;p&gt;Log in with GitHub and create a blank project. The console will automatically detect your nodes and show them on a global map at their correct geographic locations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Deployment
&lt;/h3&gt;

&lt;p&gt;Create a simple "ping-pong" function to test your cloud:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Choose your domain&lt;/strong&gt; from the dropdown.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Choose a function from the templates&lt;/strong&gt; that returns "PONG".&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Push to GitHub&lt;/strong&gt; to trigger the automatic build and deploy pipeline.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Monitor build progress&lt;/strong&gt; in the console.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Test the function&lt;/strong&gt; using the lightning bolt icon.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0aro1qw2lvww0vcfawv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0aro1qw2lvww0vcfawv.png" alt="Congrats"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;For more, see the documentation at &lt;a href="https://tau.how/" rel="noopener noreferrer"&gt;tau.how&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
      <category>selfhosted</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Spore Drive: Building a Cloud Platform in a Few Lines of Code</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Thu, 31 Oct 2024 02:04:02 +0000</pubDate>
      <link>https://dev.to/samyfodil/build-your-cloud-2nmm</link>
      <guid>https://dev.to/samyfodil/build-your-cloud-2nmm</guid>
      <description>&lt;p&gt;Building your own cloud platform has many benefits, including cost savings, ownership, sovereignty, and most importantly, the ability to make your solution self-hostable. However, constructing a cloud computing platform is a long, complex, and expensive endeavor—a problem partially solved with &lt;a href="https://github.com/taubyte/tau" rel="noopener noreferrer"&gt;Tau&lt;/a&gt;. Why only partially? Simply because, though Tau is a simple-to-deploy single binary, you still need to get that done, configure Tau, and ensure dependencies like Docker are installed. Not to mention, you have to repeat this on each host for every Tau update. If you ask me, it's not developer-friendly just yet!&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing Spore-Drive
&lt;/h3&gt;

&lt;p&gt;One option is using Infrastructure as Code (IaC) tools like Terraform or Pulumi, which come with their own complexities and learning curves—not to say these aren't developer-friendly tools. What we need is a tool that's specific to Tau, much like macOS is specific to a MacBook, delivering the best results and user experience. This is why I built &lt;strong&gt;Spore-Drive&lt;/strong&gt;, a tool that allows you to build, expand, and keep a cloud up to date with just a few lines of code.&lt;/p&gt;

&lt;p&gt;The idea is that given a configuration—which is generated or edited with code—we can determine and execute a deployment strategy. The first part relies on the concept behind &lt;a href="https://github.com/taubyte/go-seer" rel="noopener noreferrer"&gt;go-seer&lt;/a&gt;, which essentially treats a folder containing YAML files as a database. This helps keep the state in a human-readable format, and we can also commit it to a Git repository. The second part consumes the configuration and deployment parameters to build a deployment plan (called a course) and then executes it, resulting in the deployment of Tau.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;Let's consider our goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Support for multiple programming languages&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web-ready&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise in mind&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No full rewrite for each language&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these goals in mind, we need to have Spore-Drive run as a service, with clients written in many languages. Because it has to be web-ready, we'll use &lt;a href="https://connectrpc.com/" rel="noopener noreferrer"&gt;ConnectRPC&lt;/a&gt; to implement the API.&lt;/p&gt;

&lt;p&gt;The core can be written in Go—not only is it my language of choice, but many of the components we'll be using, like go-seer and &lt;a href="https://github.com/taubyte/tau/tree/main/pkg/mycelium" rel="noopener noreferrer"&gt;mycelium&lt;/a&gt;, are written in Go. Moreover, we intend to have Spore-Drive be part of Tau's CDK, which means it needs to be embedded in Tau as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Spore-Drive
&lt;/h3&gt;

&lt;p&gt;As of this article, I have only managed to create a TypeScript client. You can use Spore-Drive directly with Go, but a client is next on my list. So for this article, I'm going to use the TypeScript package.&lt;/p&gt;

&lt;h4&gt;
  
  
  Context
&lt;/h4&gt;

&lt;p&gt;I have created droplets on DigitalOcean, and I'd like to build a cloud with the main domain being &lt;code&gt;pom.ac&lt;/code&gt;, hosted by Namecheap.&lt;/p&gt;

&lt;p&gt;I need to fetch droplet information to create or update my configuration, deploy with Spore-Drive, and then update my DNS records on Namecheap.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a Project
&lt;/h4&gt;

&lt;p&gt;Let's create a TypeScript project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;typescript tsx &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit your &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES2020"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ESNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declaration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resolveJsonModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ES2020"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"displace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsx src/index.ts"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, install Spore-Drive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @taubyte/spore-drive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new file &lt;code&gt;src/index.ts&lt;/code&gt; and import Spore-Drive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;CourseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Drive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;TauLatest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Course&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@taubyte/spore-drive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configuration
&lt;/h4&gt;

&lt;p&gt;Start by creating a configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd like to open or sync your configuration to disk, pass a path like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/../config`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, initialize it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will have the Spore-Drive service create an instance of your configuration.&lt;/p&gt;

&lt;p&gt;A cloud built with Tau requires some minimal configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Root domain&lt;/strong&gt;: Identifies the cloud. For me, it's &lt;code&gt;pom.ac&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generated domain&lt;/strong&gt;: Can also be a subdomain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain validation key&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Swarm key&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cloud&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Domain&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pom.ac&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Generated&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g.pom.ac&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Validation&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cloud&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;P2P&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Swarm&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to define a signer for SSH. Here, I'm using username and password, but you can also use an SSH key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Previous code...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainAuth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Signer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mainAuth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mainAuth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROPLET_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hosts can run multiple instances of Tau; each is called a node, and each node can run multiple services grouped under what we call a shape. Here, I'm defining a shape called &lt;code&gt;all&lt;/code&gt;, which includes all services except &lt;code&gt;gateway&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Previous code...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Shapes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tns&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hoarder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;seer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;substrate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;patrick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;monkey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Ports&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4242&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Ports&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4262&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we're going to add our hosts. Here, I'm using a helper (see &lt;a href="https://github.com/taubyte/digitalocean-displacement/blob/main/src/do.ts" rel="noopener noreferrer"&gt;do.ts&lt;/a&gt;) that lists all my droplets. If the host does not exist, I add it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bootstrapers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;droplet&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;Droplets&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicIp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DropletInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;droplet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Hosts&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;bootstrapers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Addresses&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publicIp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/32`&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SSH&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publicIp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:22`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SSH&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;40.730610, -73.935242&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Shapes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Shapes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;Instance&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cloud&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;P2P&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Bootstrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bootstrapers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that I'm adding new hosts to &lt;code&gt;bootstrapers&lt;/code&gt; because the next step is making sure all these hosts can bootstrap each other. This is not a requirement—this example has two droplets—but in a larger setup, you'd like to have bootstrap nodes that do not run any service.&lt;/p&gt;

&lt;p&gt;Finally, we commit the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the call to the &lt;code&gt;createConfig&lt;/code&gt; function after initialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Drive
&lt;/h4&gt;

&lt;p&gt;Now that we have our configuration loaded, we can create a &lt;code&gt;Drive&lt;/code&gt;. It takes a reference to our configuration instance and an optional Tau version or binary. Here, I'm going to make sure hosts are running the latest Tau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Drive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Drive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TauLatest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to plot a course:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;course&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CourseConfig&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spore-Drive will determine the best strategy to deploy the latest version of Tau, while installing dependencies and making sure configuration for each node is generated.&lt;/p&gt;

&lt;p&gt;To start the deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;displace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts the deployment (or displacement, as I call it). The process is run on the service side and can be queued (in the future).&lt;/p&gt;

&lt;p&gt;To get updates on the process, you can call &lt;code&gt;progress&lt;/code&gt;, which will feed you a progress stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;displacement&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle progress updates...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each element of the stream is &lt;code&gt;DisplacementProgress&lt;/code&gt; and has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;path&lt;/strong&gt;: &lt;code&gt;/&amp;lt;course name&amp;gt;/&amp;lt;host name&amp;gt;/&amp;lt;task name&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;progress&lt;/strong&gt;: 0 to 100&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;error&lt;/strong&gt;: Error message, if any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out &lt;a href="https://github.com/taubyte/digitalocean-displacement/blob/main/src/index.ts#L30" rel="noopener noreferrer"&gt;displayProgress&lt;/a&gt; if you'd like to display the progress as progress bars.&lt;/p&gt;

&lt;h4&gt;
  
  
  Use your cloud!
&lt;/h4&gt;

&lt;p&gt;Your next step is to use your newly deployed cloud. Check &lt;a href="https://tau.how" rel="noopener noreferrer"&gt;tau.how&lt;/a&gt; for more details on that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Code
&lt;/h3&gt;

&lt;p&gt;The full code for the &lt;code&gt;pom.ac&lt;/code&gt; cloud can be found &lt;a href="https://github.com/taubyte/digitalocean-displacement/tree/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  In action
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/T4b5Vf9V1zQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Next?
&lt;/h3&gt;

&lt;p&gt;In my effort to close the gap between software development and cloud computing, I'm planning to build a similar interface for &lt;a href="https://github.com/taubyte/tau/tree/main/tools/taucorder" rel="noopener noreferrer"&gt;taucorder&lt;/a&gt;. Ultimately, both will become part of the Tau CDK.&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>devops</category>
      <category>tooling</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Ollama Cloud - Scaling Local Inference to the Cloud</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Mon, 08 Jul 2024 16:43:56 +0000</pubDate>
      <link>https://dev.to/samyfodil/building-ollama-cloud-scaling-local-inference-to-the-cloud-2i1a</link>
      <guid>https://dev.to/samyfodil/building-ollama-cloud-scaling-local-inference-to-the-cloud-2i1a</guid>
      <description>&lt;p&gt;Ollama is primarily a wrapper around &lt;code&gt;llama.cpp&lt;/code&gt;, designed for local inference tasks. It's not typically your first choice if you're looking for cutting-edge performance or features, but it has its uses, especially in environments where external dependencies are a concern.&lt;/p&gt;

&lt;h4&gt;
  
  
  Local AI Development
&lt;/h4&gt;

&lt;p&gt;When using Ollama for local AI development, the setup is straightforward but effective. Developers typically leverage Ollama to run inference tasks directly on their local machines. Here's a visual depiction of a typical local development setup using Ollama:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7trzftpx7neannmtpdo5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7trzftpx7neannmtpdo5.png" alt="Typical Local Development with Ollama"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This configuration allows developers to test and iterate quickly without the complexities of remote server communications. It's ideal for initial prototyping and development phases where quick turnaround is critical.&lt;/p&gt;

&lt;h4&gt;
  
  
  From Local to Cloud
&lt;/h4&gt;

&lt;p&gt;Transitioning from a local setup to a scalable cloud environment involves evolving from a simple 1:1 setup (one user request to one inference host) to a more complex many-to-many (multiple user requests to multiple inference hosts) configuration. This shift is necessary to maintain efficiency and responsiveness as demand increases.&lt;/p&gt;

&lt;p&gt;Here's how this scaling looks when moving from local development to production:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ol147bbr3dv5iqs9vs2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ol147bbr3dv5iqs9vs2.png" alt="View of Typical m:n Scaling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adopting a straightforward approach during this transition can significantly increase the complexity of applications, especially as sessions need to maintain consistency across various states. Delays and inefficiencies may arise if requests are not optimally routed to the best available inference host.&lt;/p&gt;

&lt;p&gt;Moreover, the complex nature of distributed applications makes them challenging to test locally, which can slow down the development process and increase the risk of failures in production environments.&lt;/p&gt;

&lt;h4&gt;
  
  
  Serverless
&lt;/h4&gt;

&lt;p&gt;Serverless computing abstracts server management and infrastructure details, allowing developers to focus solely on code and business logic. By decoupling request handling and consistency maintenance from the application, serverless architecture simplifies scaling.&lt;/p&gt;

&lt;p&gt;This approach allows the application to remain concentrated on delivering value, solving many common scaling challenges without burdening developers with infrastructure complexities.&lt;/p&gt;

&lt;h4&gt;
  
  
  WebAssembly
&lt;/h4&gt;

&lt;p&gt;WebAssembly (Wasm) addresses the challenge of dependency management by enabling the compilation of applications into self-contained modules. This makes apps easier to orchestrate and test both locally and in the cloud, ensuring consistency across different environments.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tau
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/taubyte/tau" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl430964hsamdjp6e4mo.png" alt="tau"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tau is a framework to build low-maintenance and highly scalable cloud computing platforms. It excels in simplicity and extendibility. Tau makes deployment straightforward and supports running a local cloud for development, allowing for end-to-end (E2E) testing of both the cloud infrastructure and the applications running on it.&lt;/p&gt;

&lt;p&gt;This approach, referred to by Taubyte as "Local Coding Equals Global Production," ensures that what works locally will work globally, significantly easing the development and deployment processes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Integrating Ollama into Tau with the Orbit Plugin System
&lt;/h4&gt;

&lt;p&gt;Tau’s plugin system, known as Orbit, significantly simplifies turning services into manageable components by wrapping them into WebAssembly host modules. This approach allows Tau to take over the orchestration duties, streamlining the deployment and management process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exporting Functions in Ollama
&lt;/h4&gt;

&lt;p&gt;To make Ollama functions accessible within Tau’s ecosystem, we utilize the Orbit system to export Ollama’s capabilities as callable endpoints. Here’s how you can export an endpoint in Go:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;W_pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;satellite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modelNamePtr&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modelNameSize&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pullIdptr&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelNamePtr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modelNameSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ErrorReadMemory&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updateFunc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPullId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;updateFunc&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PullModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegistryOptions&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;updateFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pullLock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pullLock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pulls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteUint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pullIdptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ErrorNone&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For a straightforward example of exporting functions, you can refer to the &lt;a href="https://github.com/taubyte/tau/tree/main/pkg/vm-orbit/examples/hello_world" rel="noopener noreferrer"&gt;hello_world example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once defined, these functions, now called via &lt;code&gt;satellite.Export&lt;/code&gt;, enable the seamless integration of Ollama into Tau’s environment:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"/tmp/ollama-wasm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;satellite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ollama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Writing Tests for the Ollama Plugin
&lt;/h4&gt;

&lt;p&gt;Testing the plugin is streamlined and straightforward. Here's how you can write a serverless function test in Go:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="c"&gt;//export pull&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gemma:2b-instruct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to call pull"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using Tau's test suite and Go builder tools, you can build your plugin, deploy it in a test environment, and execute the serverless functions to verify functionality:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestPull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;span class="c"&amp;gt;// Create a testing suite to test the plugin&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;ts&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;:=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;suite&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;New&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;ctx&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;assert&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;NilError&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;

&amp;lt;span class="c"&amp;gt;// Use a Go builder to build plugins and wasm&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;gob&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;:=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;builder&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;New&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt;

&amp;lt;span class="c"&amp;gt;// Build the plugin from the directory&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;wd&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;_&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;:=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;os&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Getwd&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;pluginPath&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;:=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;gob&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Plugin&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;path&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Join&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;wd&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"."&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;),&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"ollama"&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;assert&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;NilError&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;

&amp;lt;span class="c"&amp;gt;// Attach plugin to the testing suite&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;ts&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;AttachPluginFromPath&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;pluginPath&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;assert&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;NilError&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;

&amp;lt;span class="c"&amp;gt;// Build a wasm file from serverless function&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;wasmPath&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;:=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;gob&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Wasm&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;ctx&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;path&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Join&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;wd&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"fixtures"&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"pull.go"&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;),&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;path&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Join&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;wd&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"fixtures"&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"common.go"&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;))&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;assert&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;NilError&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;

&amp;lt;span class="c"&amp;gt;// Load the wasm module and call the function&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;module&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;:=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;ts&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;WasmModule&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;wasmPath&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;assert&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;NilError&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;

&amp;lt;span class="c"&amp;gt;// Call the "pull" function from our wasm module&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;_&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;module&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;Call&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;ctx&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="s"&amp;gt;"pull"&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="n"&amp;gt;assert&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;NilError&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="n"&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;err&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Code&lt;br&gt;
&lt;/h4&gt;

&lt;p&gt;You can find the complete code here &lt;a href="https://github.com/ollama-cloud/ollama-as-wasm-plugin/tree/main/tau" rel="noopener noreferrer"&gt;https://github.com/ollama-cloud/ollama-as-wasm-plugin/tree/main/tau&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What's Next?
&lt;/h4&gt;

&lt;p&gt;You can now build LLM applications with ease. Here are the steps to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ollama-cloud/get-started/blob/main/README.md#set-up-your-local-environment" rel="noopener noreferrer"&gt;Start locally using &lt;code&gt;dream&lt;/code&gt;&lt;/a&gt;: Set up your local environment to develop and test your application.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tau.how/01-getting-started/02-first-project/" rel="noopener noreferrer"&gt;Create a project&lt;/a&gt;: Begin a new project with Tau to harness its full potential.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tau.how/01-getting-started/04-deploy-a-cloud/" rel="noopener noreferrer"&gt;Create your production cloud&lt;/a&gt;: Deploy your project in a production cloud environment.&lt;/li&gt;
&lt;li&gt;Drop the plugin binary in the &lt;code&gt;/tb/plugins&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Import your project into production&lt;/li&gt;
&lt;li&gt;Show off!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloudcomputing</category>
      <category>rag</category>
      <category>webassembly</category>
      <category>go</category>
    </item>
    <item>
      <title>Building a Cloud Development Kit (CDK)</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Wed, 03 Jul 2024 07:39:46 +0000</pubDate>
      <link>https://dev.to/samyfodil/building-a-cloud-development-kit-cdk-3lgd</link>
      <guid>https://dev.to/samyfodil/building-a-cloud-development-kit-cdk-3lgd</guid>
      <description>&lt;h3&gt;
  
  
  What Exactly is a Cloud Development Kit (CDK)?
&lt;/h3&gt;

&lt;p&gt;Imagine you're a developer who needs to set up a bunch of cloud resources. Traditionally, you might deal with endless lines of JSON or YAML configurations. It's precise but can get pretty tedious, right? Well, this is where a Cloud Development Kit, or CDK, comes in handy. Instead of those endless configuration files, you use a programming language you’re already comfortable with—like TypeScript, Python, or Java. This means you can code your cloud infrastructure just like you’d code anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is the CDK a Game Changer?
&lt;/h3&gt;

&lt;p&gt;Let’s break it down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Productivity on Steroids&lt;/strong&gt;: Forget about switching gears between applications and infrastructure. Now, it's all in one place, with tools you already love (and understand!). Autocomplete, refactoring, and error checking are right there with you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reuse and Recycle&lt;/strong&gt;: Craft a piece of infrastructure once, wrap it up into a component, and reuse it anywhere you need it. This not only saves time but also keeps your setups consistent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tailor-Made Solutions&lt;/strong&gt;: Extend the basic setups with your own tweaks. Need a special kind of storage or a unique authentication method? Just code it in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparent and Controlled&lt;/strong&gt;: It’s all in your codebase, visible and version-controlled. Every change is clear and trackable—no surprises.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  AWS CDK
&lt;/h3&gt;

&lt;p&gt;AWS was one of the first to jump on this bandwagon with their CDK. It takes the power of AWS CloudFormation and makes it friendlier. Instead of wading through those YAML or JSON templates, you write in a comfortable, expressive programming language.&lt;/p&gt;

&lt;p&gt;Here’s an example of AWS CDK with TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-cdk/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-cdk/aws-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCloudStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Setting up an S3 bucket with version control&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyFirstBucket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;versioned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;removalPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RemovalPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DESTROY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyCloudStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyCloudStack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how intuitive and straightforward defining cloud resources can be with CDK. It’s just like writing any other piece of software!&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS CDK Workflow Explained
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxiom683wjzusnmnqtn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxiom683wjzusnmnqtn6.png" alt="AWS CDK Workflow" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AWS Cloud Development Kit (AWS CDK) utilizes a sophisticated workflow that integrates various AWS services to provide a seamless development and deployment experience. Here’s a breakdown of the typical workflow and how it leverages these services:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define Infrastructure as Code&lt;/strong&gt;: You start by defining your cloud resources using familiar programming languages such as TypeScript or Python. This code defines what resources you need, such as databases, storage buckets, or compute instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Synthesis&lt;/strong&gt;: The AWS CDK app takes this high-level code and compiles it into a lower-level CloudFormation template. This process, known as synthesis, involves the CDK CLI (&lt;code&gt;cdk synth&lt;/code&gt;) transforming your declarative setup into a set of instructions that AWS CloudFormation can understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;: Once the CloudFormation template is synthesized, you deploy it using the CDK CLI (&lt;code&gt;cdk deploy&lt;/code&gt;). This command instructs AWS CloudFormation to provision and manage the resources as specified in the template. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Utilization of AWS Services&lt;/strong&gt;: Throughout this process, AWS CDK interacts with various AWS services like AWS CodePipeline and AWS CodeCommit for continuous integration and delivery, enhancing the CI/CD pipeline's efficiency and robustness.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Building a CDK
&lt;/h3&gt;

&lt;p&gt;Now that we understand what a CDK is, let's look at designing one for a cloud platform. Here, I'll be focusing on &lt;a href="https://github.com/taubyte/tau"&gt;tau&lt;/a&gt;, an open-source CDN PaaS I founded.&lt;/p&gt;

&lt;p&gt;Tau uses YAML for resource definition. This approach is not unique; Kubernetes and many other platforms use YAML as well. However, what sets tau apart is its design philosophy: Git is the single source of truth. This means there are no APIs to call for defining resources like storage buckets. Instead, everything is managed through Git.&lt;/p&gt;

&lt;p&gt;This design is advantageous because it essentially provides us with an equivalent to AWS CloudFormation, but integrated directly with Git. This tight integration simplifies infrastructure management and makes it inherently version-controlled and collaborative.&lt;/p&gt;

&lt;p&gt;All we need to do is figure out a way to generate and edit YAML files with code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Schema Package
&lt;/h3&gt;

&lt;p&gt;Because Tau is a cloud platform you can write tests for, we already built a package called &lt;a href="https://github.com/taubyte/tau/tree/main/pkg/schema"&gt;schema&lt;/a&gt; to manipulate YAML configuration files. The catch is that it has to be in Go, while most CDKs at least support JavaScript/TypeScript and Python.&lt;/p&gt;

&lt;p&gt;This creates a challenge: how can we extend our CDK to support these popular languages while leveraging the existing schema package?&lt;/p&gt;

&lt;h3&gt;
  
  
  WebAssembly
&lt;/h3&gt;

&lt;p&gt;Go is one of the first languages that supported WebAssembly as a compilation target. Additionally, most programming languages either have a native implementation or bindings for a WebAssembly runtime. &lt;/p&gt;

&lt;p&gt;So, if we compile the &lt;a href="https://github.com/taubyte/tau/tree/main/pkg/schema"&gt;schema package&lt;/a&gt; into a WebAssembly module, we should be able to call it from a variety of languages. This approach leverages the strengths of Go and the flexibility of WebAssembly, making it possible to interact with Tau's infrastructure definitions from languages like JavaScript, TypeScript, and Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extism
&lt;/h3&gt;

&lt;p&gt;Writing code to initiate a WebAssembly runtime, load our module, and call exported functions can be quite a lot of work. Luckily, the team at &lt;a href="https://dylibso.com/"&gt;dylibso&lt;/a&gt; has thought about that and built &lt;a href="https://extism.org/"&gt;Extism&lt;/a&gt;, a framework for building plugins with WebAssembly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of Extism Plugin
&lt;/h3&gt;

&lt;p&gt;Here’s a simple example of a Go plugin using Extism:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/extism/go-pdk"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;//export greet&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`Hello, `&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;`!`&lt;/span&gt;
    &lt;span class="n"&gt;pdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OutputString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Loading and calling &lt;code&gt;greet&lt;/code&gt; from JavaScript is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;createPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@extism/extism&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin.wasm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;useWasi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;greet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Samy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Extism, we can easily compile our Go code into WebAssembly and call it from other languages like JavaScript, making the integration process seamless and efficient. This capability significantly reduces the complexity of working with WebAssembly, enabling us to extend Tau’s CDK functionalities to various programming environments effortlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Plugin
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/taubyte/tau/tree/main/cdk/plugin"&gt;plugin&lt;/a&gt; is a wrapper around the schema package that uses the Extism PDK. Just like schema, the first step involves opening a project by reading a folder that contains configuration files (the folder can also be empty).&lt;/p&gt;

&lt;p&gt;Here's how you can do it in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/extism/go-pdk"&lt;/span&gt;
    &lt;span class="n"&gt;proj&lt;/span&gt; &lt;span class="s"&gt;"github.com/taubyte/tau/pkg/schema/project"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="n"&gt;proj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;

&lt;span class="c"&gt;//export openProject&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;openProject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;proj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SystemFS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/mnt"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might notice the global variable &lt;code&gt;project&lt;/code&gt;. This isn't a novice mistake:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We will load the module each time we open a project.&lt;/li&gt;
&lt;li&gt;WebAssembly is single-threaded, at least for now.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The JavaScript CDK
&lt;/h3&gt;

&lt;p&gt;On the JavaScript side, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;createPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@extism/extism&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;core&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;coreWasmPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../core.wasm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;coreWasmPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;useWasi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;allowedPaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/mnt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mountPath&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function, &lt;code&gt;core&lt;/code&gt;, loads the module and attaches the folder containing the configuration files to it as &lt;code&gt;/mnt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To open a project, we load the Wasm module, call &lt;code&gt;openProject&lt;/code&gt;, and then return a &lt;code&gt;Project&lt;/code&gt; object that references an instance of the core module initialized to our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;core&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openProject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, we can write code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@taubyte/cdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path/to/folder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// other configurations&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;p&gt;Now that we have a CDK, the next step is to integrate it with Tau's CI/CD workflow. This integration will enable seamless deployment and management of cloud resources directly from your development pipeline. I’ll cover this integration in a separate article, where we will dive into the specifics of automating your deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we explored what a Cloud Development Kit (CDK) is and why it’s a game changer for cloud infrastructure management. We looked at how AWS CDK simplifies defining and deploying cloud resources using familiar programming languages.&lt;/p&gt;

&lt;p&gt;By leveraging WebAssembly and the Extism framework, we were able to create a versatile CDK that supports multiple languages, making tau’s infrastructure management more accessible and efficient. &lt;/p&gt;

&lt;p&gt;My vision, is that this will evolve to also allows developers to embed infrastructure definitions directly within their application code, providing a seamless and cohesive development experience.&lt;/p&gt;

&lt;p&gt;Stay tuned for the next article, where we’ll dive into integrating the CDK with tau’s CI/CD workflow.&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>cdk</category>
      <category>webassembly</category>
      <category>cloudpractitioner</category>
    </item>
    <item>
      <title>🔥 10x the odds of landing a Go job 🔥</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Sun, 12 May 2024 05:18:08 +0000</pubDate>
      <link>https://dev.to/samyfodil/10x-the-odds-of-landing-a-go-job-86m</link>
      <guid>https://dev.to/samyfodil/10x-the-odds-of-landing-a-go-job-86m</guid>
      <description>&lt;p&gt;First it was the market, and now it's AI. Let's face it, landing a developer job nowadays is challenging, even for non-JavaScript positions—and it's even harder for junior developers!&lt;/p&gt;

&lt;p&gt;So the question is: How can you stand out?&lt;/p&gt;

&lt;p&gt;Most software developers gravitate toward JavaScript and Python because, although they are not the easiest to debug, they are the easiest to learn. Guess what? Large Language Models (LLMs) excel in these languages as well. By choosing less common languages like Go, you're already improving your job prospects. Just to be clear, I'm not saying these languages are bad; every language has its pros and cons.&lt;/p&gt;

&lt;p&gt;If you're a junior Go developer, you likely started by building some ORM-based backends in Go. Think about it; it's what everybody does: it's easy and familiar. But this approach does not help you build the real skills that set you apart.&lt;/p&gt;

&lt;p&gt;Go is very popular in infrastructure; just look at Terraform, Kubernetes, and many other extremely popular projects—they are all built in Go. Some, like Kubernetes, even have a pure-Go policy.&lt;/p&gt;

&lt;p&gt;I hope at this point you see where I'm going: If I have in front of me a list of candidates and one of them demonstrates they can go beyond the ORM use-case, that person will definitely get an interview!&lt;/p&gt;

&lt;p&gt;Now, without professional experience, how would you demonstrate or at least signal that you're a Go-wiz? The answer is simple: contributing to open-source projects.&lt;/p&gt;

&lt;p&gt;You have to choose the projects you'd like to contribute to very carefully. Larger projects may not have many issues for a junior developer; however, it might take forever to get your PR merged, if it even makes it there.&lt;/p&gt;

&lt;p&gt;The great news is there are a lot of newer projects in the infrastructure space. These projects have easy-to-tackle issues and will be more willing to work with you and even merge your PRs very quickly.&lt;/p&gt;

&lt;p&gt;Here are a few projects you should consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/taubyte/tau"&gt;Tau&lt;/a&gt;&lt;/strong&gt; - Open-source Cloud Computing Platform on Autopilot.
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23jjewrsh11s35ag55ss.png" alt="Tau Project Screenshot" width="800" height="600"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/drand/drand"&gt;Drand&lt;/a&gt;&lt;/strong&gt; - A Distributed Randomness Beacon Daemon - Go implementation.
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhi93ba1v4opk5brljhc.png" alt="Drand Project Screenshot" width="800" height="600"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/kcl-lang/kcl"&gt;KCL&lt;/a&gt;&lt;/strong&gt; - KCL Programming Language (CNCF Sandbox Project).
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xlroims4mam9bzt629x.png" alt="KCL Project Screenshot" width="800" height="600"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/apache/incubator-fury"&gt;Fury&lt;/a&gt;&lt;/strong&gt; - A blazingly fast multi-language serialization framework powered by JIT and zero-copy.
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg5sua01zo6zkgkdce2z.png" alt="Fury Project Screenshot" width="800" height="600"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/apache/camel-k"&gt;Camel-K&lt;/a&gt;&lt;/strong&gt; - Apache Camel K is a lightweight integration platform, born on Kubernetes, with serverless superpowers.
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63vxs7h3zh0ya5aj0fac.png" alt="Camel-K Project Screenshot" width="800" height="600"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before you dig in, a few things you should keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How complex is the setup&lt;/strong&gt;: Generally not an issue with Go projects unless you see a Makefile at the root of the repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How many contributors&lt;/strong&gt;: If the project has a lot of contributors, you should expect a longer time for your PR to get accepted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is there any issue with the 'good first issue' label&lt;/strong&gt;: You don't have time nor enough knowledge of the repository to create your own issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this advice helps you enhance your Go skills and boosts your chances in the job market!&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>beginners</category>
      <category>job</category>
    </item>
    <item>
      <title>Introducing A Framework for Building Cloud Computing Platforms</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Tue, 06 Feb 2024 04:46:29 +0000</pubDate>
      <link>https://dev.to/samyfodil/introducing-a-framework-to-build-cloud-computing-platforms-52ip</link>
      <guid>https://dev.to/samyfodil/introducing-a-framework-to-build-cloud-computing-platforms-52ip</guid>
      <description>&lt;p&gt;If you're reading this, chances are you're either curious about the next big thing in cloud computing or you're actively seeking ways to enhance your development workflow. As the creator of Taubyte, I'm here to share a journey into the future of cloud computing—a future we're building to be as intuitive as software development itself. This isn't just another tool; it's a paradigm shift designed with you, the developer, at heart.&lt;/p&gt;

&lt;p&gt;Taubyte simplifies the process of building a cloud computing platform, making it a no-brainer. Unlike other products, such as Kubernetes, which were not designed with software developers in mind nor as platforms, Taubyte eliminates the need for DevOps and platform engineering. In essence, Taubyte is designed for software developers, requiring no DevOps nor platform engineering skills. To achieve this, we aimed not just for automation but for autonomy.&lt;/p&gt;

&lt;p&gt;If you're a DevOps professional reading this, you might think it sounds too good to be true, or perhaps you're inclined to deny its feasibility, fearing it will make your job obsolete. However, I invite you to stay with us because Taubyte is as real as it is open source. Moreover, I believe it will give DevOps and Platform Engineers an unprecedented advantage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's get our hands dirty!
&lt;/h2&gt;

&lt;p&gt;The best way to learn something is by doing it, and that's exactly what we're going to do. All you need is &lt;code&gt;npm&lt;/code&gt;. While there are other methods, we'll stick to &lt;code&gt;npm&lt;/code&gt; as it's the simplest and most widely available, even on Windows.&lt;/p&gt;

&lt;p&gt;What we'll do is install &lt;code&gt;dreamland&lt;/code&gt;, a project hosted on &lt;a href="https://github.com/taubyte/dreamland"&gt;github.com/taubyte/dreamland&lt;/a&gt; that allows you to run a Taubyte-based Cloud Computing Platform locally. It's an excellent tool for local development and testing, but we'll use it in a slightly different way.&lt;/p&gt;

&lt;p&gt;Run the following command to install dreamland:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i @taubyte/dream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you should have the &lt;code&gt;dream&lt;/code&gt; command-line tool available. Let's start a cloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dream new multiverse
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Dreamland ready
&lt;span class="o"&gt;[&lt;/span&gt;SUCCESS] Universe blackhole started!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can ignore any ERROR messages you might see about &lt;code&gt;seer&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you see &lt;code&gt;SUCCESS&lt;/code&gt;, it means your cloud has been fully started.&lt;/p&gt;

&lt;h2&gt;
  
  
  A first look
&lt;/h2&gt;

&lt;p&gt;First, let's explore what's happening using the command line. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dream status universe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should output something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────┬─────────────────────┬────────┬───────┐
│ Nodes │ elder@blackhole     │ p2p    │ 14051 │
│       ├─────────────────────┼────────┼───────┤
│       │ tns@blackhole       │ http   │ 14466 │
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lists all the running nodes. Each node could be running a specific protocol (e.g., tns or substrate) and will reflect that. Others will have a role like elder (bootstrap node) or client.&lt;/p&gt;

&lt;p&gt;Also, &lt;code&gt;@blackhole&lt;/code&gt; indicates that the node is part of the blackhole universe. Each universe represents a cloud and is cryptographically isolated from any other cloud on the peer-to-peer layer.&lt;/p&gt;

&lt;p&gt;On the right side, you can see the TCP ports each node is using along with the number of copies.&lt;/p&gt;

&lt;p&gt;Now, let's leave the terminal and head to &lt;a href="https://console.taubyte.com"&gt;console.taubyte.com&lt;/a&gt; where you're going to locate the Dreamland button. Then click on it.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wrRVA0ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-btn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wrRVA0ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-btn.png" alt="screenshot" width="398" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The button will be disabled or hidden if dreamland is not detected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, locate the sidebar: (1) click on Network, then (2) on blackhole.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t1BHokdP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-select-universe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t1BHokdP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-select-universe.png" alt="screenshot" width="350" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a few seconds, you should see something similar to:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dr--Il6M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-universe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dr--Il6M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-universe.png" alt="screenshot" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the network graph, which you can manipulate, you can see all the same nodes as before from the CLI.&lt;/p&gt;

&lt;p&gt;If you hover over any node, it'll display the TCP ports it's using.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2G45WJnR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-hover-node.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2G45WJnR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-hover-node.png" alt="screenshot" width="202" height="230"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What's with the mesh network?
&lt;/h2&gt;

&lt;p&gt;Hosts, or as we call them, Nodes, form a Taubyte-based Cloud Computing Platform and communicate with each other using a peer-to-peer network. Running locally through dreamland, all the nodes are interconnected, although this might not always be the case in production, especially if you have many nodes.&lt;/p&gt;

&lt;p&gt;The peer-to-peer nature of Taubyte-based clouds gives them important characteristics like resilience and redundancy.&lt;/p&gt;
&lt;h2&gt;
  
  
  Protocols
&lt;/h2&gt;

&lt;p&gt;While in production a node can run multiple protocols by defining a shape (a term reminiscent of the internal name &lt;code&gt;tau&lt;/code&gt; had: &lt;code&gt;odo&lt;/code&gt;, a reference to the shape-shifting Star Trek character), in dreamland, each node runs only one protocol. This design choice simplifies protocol debugging.&lt;/p&gt;

&lt;p&gt;Without further ado, here's what each protocol does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;auth&lt;/code&gt; handles token validation and secret management.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tns&lt;/code&gt; ensures project registry consistency across the cloud.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seer&lt;/code&gt; is responsible for DNS resolution and load balancing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;patrick&lt;/code&gt; bridges git events into CI/CD jobs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;monkey&lt;/code&gt; executes CI/CD jobs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hoarder&lt;/code&gt; manages replication.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;substrate&lt;/code&gt; handles request processing and serving.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gateway&lt;/code&gt; manages L7 load-balancing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The other nodes
&lt;/h2&gt;

&lt;p&gt;The other nodes, referred to as Simples (admittedly, not the best name), include &lt;code&gt;elder&lt;/code&gt; and &lt;code&gt;client&lt;/code&gt;. While they are not crucial for the purpose of this article and could be excluded when starting the universe, it's helpful to understand their intended roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;elder&lt;/code&gt; nodes are used for bootstrapping. Since &lt;code&gt;dreamland&lt;/code&gt; interconnects all nodes, an &lt;code&gt;elder&lt;/code&gt; is included for testing purposes when using &lt;a href="https://github.com/taubyte/tau/tree/main/libdream"&gt;libdream&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;client&lt;/code&gt; nodes are lightweight and can be used to test protocols or peer-to-peer services deployed on the cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Some &lt;code&gt;fixtures&lt;/code&gt;, which will be covered in another article, may require Simples to function correctly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a project
&lt;/h2&gt;

&lt;p&gt;Now, let's create a project on this cloud. Although it can be done using &lt;a href="https://github.com/taubyte/tau-cli"&gt;tau-cli&lt;/a&gt;, which you might prefer if you're a terminal enthusiast like me, we're going to use the &lt;a href="https://console.taubyte.com"&gt;Web Console&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;Open a new browser window or tab and navigate to &lt;a href="https://console.taubyte.com"&gt;console.taubyte.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(1) Type your email, then (2) click on the network selection input, and finally (3) click on &lt;code&gt;Dreamland/blackhole&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M2wcnK10--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-login-select-network.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M2wcnK10--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-login-select-network.png" alt="screenshot" width="395" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click the &lt;code&gt;Login with GitHub&lt;/code&gt; button.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VhLYDeCY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-login-github.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VhLYDeCY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-login-github.png" alt="screenshot" width="396" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be asked to grant the app GitHub access. This access is local to your browser and is used to create repositories related to your project, which will be cloned into a browser-based virtual file system.&lt;/p&gt;

&lt;p&gt;The next screen will display "Your projects" and should show no projects. You'll want to click on &lt;code&gt;Create project&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xjvr0Rtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-project-btn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xjvr0Rtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-project-btn.png" alt="screenshot" width="456" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter a project name, a description, toggle private (unless you want the project repositories to be public), then click on &lt;code&gt;Create Project&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Po-kFI4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-project-modal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Po-kFI4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-project-modal.png" alt="screenshot" width="517" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Web Console will create two repositories: one for configuration, containing mainly YAML files, and another for inline code, containing code in different languages to be compiled to WebAssembly. If everything goes well, you'll be directed to the dashboard.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P4-IBuka--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-project-dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4-IBuka--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-project-dashboard.png" alt="screenshot" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a Function
&lt;/h2&gt;

&lt;p&gt;Taubyte-based Clouds support serverless functions. Let's create one!&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Functions&lt;/code&gt; in the side menu, then on the &lt;code&gt;+&lt;/code&gt; button.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sFL-fHex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-dash.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sFL-fHex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-dash.png" alt="screenshot" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To expedite the process, we'll use a template. Skip filling any field for now and click on the &lt;code&gt;Template Select&lt;/code&gt; button.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uHgVVILB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-modal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uHgVVILB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-modal.png" alt="screenshot" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This action opens another modal at the top where you can select a template. Although you can choose Go, Rust, or AssemblyScript at the time of writing this article, we'll keep it simple and go for Go! (pun intended). So: (1) select Go, (2) select &lt;code&gt;ping_pong&lt;/code&gt;, and finally (3) close the modal.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3KXPhuBf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-template.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3KXPhuBf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-template.png" alt="screenshot" width="800" height="903"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All fields have been automatically filled except for the domains. Proceed by (1) clicking on the list and (2) selecting GeneratedDomain. This action will create a domain resource for you.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_rV_asfC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-generated-domain.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_rV_asfC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-generated-domain.png" alt="screenshot" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's worth noting that the Web Console clones your repositories in-browser, meaning there's always a code equivalent to everything you do. Let's review the YAML config by clicking on the &lt;code&gt;Yaml&lt;/code&gt; tab.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zXxHrUXQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-go-to-yaml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zXxHrUXQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-go-to-yaml.png" alt="screenshot" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see YAML code resembling the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Returns pong to a ping over HTTP&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
&lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
  &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/ping&lt;/span&gt;
&lt;span class="na"&gt;domains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GeneratedDomain&lt;/span&gt;
&lt;span class="na"&gt;execution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
  &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10MB&lt;/span&gt;
  &lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ping&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of this YAML should be self-explanatory, but let me clarify a few points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;source&lt;/code&gt;: can either be &lt;code&gt;.&lt;/code&gt; for inline code or the name of a library (to be explored in other articles).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execution.call&lt;/code&gt;: specifies the function to be executed and must be exported by the WebAssembly module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, let's inspect the code. The Web Console features a modest code editor useful for quick inline code updates. Access it by clicking on the &lt;code&gt;Code&lt;/code&gt; tab.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nJNZaG2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-go-to-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nJNZaG2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-go-to-code.png" alt="screenshot" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the editor, you will observe (1) the usual Go files including go.mod, (2) the code for our handler function &lt;code&gt;ping&lt;/code&gt;, and (3) a &lt;code&gt;.taubyte&lt;/code&gt; folder defining how the function is built.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vl3XRx5q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vl3XRx5q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-code.png" alt="screenshot" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While understanding the entire code or mastering Go isn't necessary, I'll explain a few basic concepts that will map in a way or another to any serverless function in supported languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The package name can be anything except &lt;code&gt;main&lt;/code&gt;. The building container, &lt;code&gt;taubyte/go-wasi&lt;/code&gt; on Docker Hub, wraps your function in a special &lt;code&gt;main&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;github.com/taubyte/go-sdk&lt;/code&gt; package simplifies interactions with the Taubyte VM, making it straightforward to use VM primitives.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;tinygo&lt;/code&gt; to compile Go into small, efficient WebAssembly modules. To export a function, annotate it with the &lt;code&gt;//export&lt;/code&gt; comment.&lt;/li&gt;
&lt;li&gt;Taubyte supports various trigger types, so handlers receive an event. We care about efficiency, so &lt;code&gt;event.Event&lt;/code&gt; is  really a wrapper of a &lt;code&gt;uint32&lt;/code&gt;, minimizing unnecessary memory allocation and copying.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;code&gt;Done&lt;/code&gt; to proceed.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XV_zn-kC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-done.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XV_zn-kC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-done.png" alt="screenshot" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function should now appear listed.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gaBg_KTC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-listed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gaBg_KTC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-listed.png" alt="screenshot" width="574" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything done so far is confined to the virtual filesystem in your browser. To apply these changes, we need to push them. Find the green button at the bottom right of the screen and click on it.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HHabJCE2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HHabJCE2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push.png" alt="screenshot" width="163" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A modal will guide you through the code changes, starting with configuration changes. Click on the domains folder, then open the GeneratedDomain.yaml file.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eevTShk0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push-001.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eevTShk0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push-001.png" alt="screenshot" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the FQDN generated for you as we will need it later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;fqdn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gftxhd6h0.blackhole.localtau&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click on Next to review code changes.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mmrp7z0S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push-002.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mmrp7z0S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push-002.png" alt="screenshot" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One more click on Next takes you to the final step, where you'll (1) enter a commit message and (2) push the changes to GitHub.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OoRA0h4w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push-003.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OoRA0h4w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-push-003.png" alt="screenshot" width="800" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In production, this push would trigger an event captured by &lt;code&gt;patrick&lt;/code&gt;. However, because we're using &lt;code&gt;dreamland&lt;/code&gt; and GitHub cannot reach your nodes directly, we run a fixture called &lt;code&gt;push-all&lt;/code&gt; to emulate the git events. Switch back to your terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dream inject push-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Return to the Web Console and, on the side menu, click on &lt;code&gt;Builds&lt;/code&gt;. You should see two CI/CD jobs, one for configuration and one for code.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RI_3PHPy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-build.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RI_3PHPy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-build.png" alt="screenshot" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a few seconds, the build should complete. Click on &lt;code&gt;Refresh&lt;/code&gt; if it seems delayed. Then, click on the stack icon to view the ping_pong function.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDSSrOWi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-build-open-details.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDSSrOWi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-build-open-details.png" alt="screenshot" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Executing the Function
&lt;/h2&gt;

&lt;p&gt;Now that our function has been built and its configuration published on &lt;code&gt;tns&lt;/code&gt;, we can execute it by hitting the endpoint. Since we're running a local cloud, we need to find out which port the &lt;code&gt;substrate&lt;/code&gt; (or &lt;code&gt;gateway&lt;/code&gt;, if you're using one) node uses to handle HTTP requests. To do this, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dream status substrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, the HTTP port is 14529.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────┬────────┬───────┐
│ substrate@blackhole │ copies │     1 │
│                     ├────────┼───────┤
│                     │ dns    │ 14304 │
│                     ├────────┼───────┤
│                     │ http   │ 14529 │
│                     ├────────┼───────┤
│                     │ p2p    │ 14282 │
└─────────────────────┴────────┴───────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can test the function using &lt;code&gt;curl&lt;/code&gt; as follows, making sure to replace &lt;code&gt;gftxhd6h0.blackhole.localtau&lt;/code&gt; with your own generated domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: gftxhd6h0.blackhole.localtau"&lt;/span&gt; http://127.0.0.1:14529/ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can add the generated domain to your local hosts file (&lt;code&gt;/etc/hosts&lt;/code&gt; in my case) as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vi /etc/hosts
127.0.0.1 gftxhd6h0.blackhole.localtau
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and exit, then run &lt;code&gt;curl&lt;/code&gt; again but without the &lt;code&gt;Host&lt;/code&gt; header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://gftxhd6h0.blackhole.localtau:14529/ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've added the generated domain to your &lt;code&gt;/etc/hosts&lt;/code&gt;, you can also use the Web Console to hit the function's endpoint: (1) In the sidebar, click on &lt;code&gt;Functions&lt;/code&gt;, then (2) click on the thunder icon.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nzwi_Tyq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-exec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nzwi_Tyq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-exec.png" alt="screenshot" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This action opens a new tab where you should see something like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hQigxauh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-exec-done.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hQigxauh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/webconsole-dreamland-new-function-exec-done.png" alt="screenshot" width="590" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You've successfully created a cloud and executed a serverless function on it!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Just Happened!
&lt;/h2&gt;

&lt;p&gt;In this section, we'll take a step back to review the processes and protocols involved in each step of deploying and executing a serverless function with Taubyte. This overview will help clarify the interactions between different components and the significance of each protocol in the overall architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Creation
&lt;/h3&gt;

&lt;p&gt;The creation of a project is predominantly a client-side operation, facilitated by either the Web Console or the tau-cli. This process involves direct communication with GitHub to establish the necessary repositories. Only towards the end does the &lt;code&gt;auth&lt;/code&gt; protocol come into play, tasked with registering these repositories. This registration process includes storing critical secrets such as the deployment key, essential for cloning code during CI/CD processes, and the webhook secret, used to authenticate events coming from GitHub.&lt;/p&gt;

&lt;p&gt;The sequence diagram below illustrates these interactions in detail:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y8DdifVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y8DdifVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-0.png" alt="Mermaid diagram diagram-0.png" width="730" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pushing Changes to GitHub
&lt;/h3&gt;

&lt;p&gt;When changes are pushed to GitHub, a sequence of events is triggered, initiating a process that involves multiple protocols to manage and execute CI/CD jobs. The &lt;code&gt;patrick&lt;/code&gt; protocol plays a pivotal role in verifying the legitimacy of events and creating jobs, while the &lt;code&gt;monkey&lt;/code&gt; protocol is responsible for the execution of these jobs. Subsequently, the &lt;code&gt;tns&lt;/code&gt; stores and replicates the compiled configuration, and the &lt;code&gt;hoarder&lt;/code&gt; protocol ensures the replication of updated assets.&lt;/p&gt;

&lt;p&gt;The sequence diagram below visualizes this workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CyarkzJt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CyarkzJt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-1.png" alt="Mermaid diagram diagram-1.png" width="784" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's important to note that because we are using Dreamland, a simulated environment, there's no direct way for GitHub to communicate with your nodes. This limitation is addressed by using the fixture called &lt;code&gt;push-all&lt;/code&gt;, which emulates the git events that would typically trigger the CI/CD process in a production environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hitting the Endpoint
&lt;/h3&gt;

&lt;p&gt;The process for handling a request at an endpoint varies depending on the network's configuration. In a simple setup without gateways and HTTPS, the request's host name is resolved by the &lt;code&gt;seer&lt;/code&gt; protocol before the request itself is processed by a &lt;code&gt;substrate&lt;/code&gt; node. However, in networks with gateways or HTTPS requests, additional steps, like retreiving x509 certificate from &lt;code&gt;auth&lt;/code&gt;, are involved.&lt;/p&gt;

&lt;p&gt;The diagrams below detail these processes for different configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without Gateway and HTTPS:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j0wrV7Ka--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j0wrV7Ka--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-2.png" alt="Mermaid diagram diagram-2.png" width="784" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With Gateway:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A0CDGYyk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A0CDGYyk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-3.png" alt="Mermaid diagram diagram-3.png" width="784" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With HTTPS:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u2Wqtovk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u2Wqtovk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/samyfodil/devto_articles/main/posts/assets/introduction-to-taubyte/diagram-4.png" alt="Mermaid diagram diagram-4.png" width="692" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Taubyte supports the Automatic Certificate Management Environment (ACME) protocol for auto-generating certificates using Let’s Encrypt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These diagrams demonstrate the seamless and autonomous nature of the Taubyte platform, which requires no manual configuration and ensures a smooth deployment and execution process for serverless functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Glimpse into the Future
&lt;/h2&gt;

&lt;p&gt;This article is but a gateway into the vast potential that Taubyte unlocks. Through a hands-on demonstration of setting up a cloud environment and deploying serverless functions, I hope to have given you a taste of the simplicity and efficiency Taubyte brings to cloud computing.&lt;/p&gt;

&lt;p&gt;Our mission with Taubyte is to democratize cloud development, making it as natural and creative as the development process itself. Whether you're venturing into the cloud for the first time or you're a seasoned developer seeking to streamline your processes, Taubyte is designed to empower your innovation.&lt;/p&gt;

&lt;p&gt;As we embark on this journey together, I invite you to explore, to experiment, and to contribute. With Taubyte, the future of cloud computing is not just about technology; it's about the community and creativity it fosters. Welcome to a new era of cloud computing, where the skies are not the limit—they're just the beginning.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>devtools</category>
      <category>webassembly</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Harnessing LLM with WebAssembly</title>
      <dc:creator>Samy Fodil</dc:creator>
      <pubDate>Tue, 07 Nov 2023 16:38:37 +0000</pubDate>
      <link>https://dev.to/samyfodil/harnessing-llm-with-webassembly-19m3</link>
      <guid>https://dev.to/samyfodil/harnessing-llm-with-webassembly-19m3</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JsDCnRao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9o4shpf0ateqs9muf3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JsDCnRao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9o4shpf0ateqs9muf3k.png" alt="Image description" width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
In the cloud computing ecosystem, infusing applications with the power of Language Learning Models (LLMs) has become increasingly accessible. This article will guide you through integrating an LLM into your cloud project, utilizing the capabilities of WebAssembly (WASM) within the open-source framework of the 8bit.ws cloud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM Capabilities via 8bit.ws Cloud&lt;/strong&gt;&lt;br&gt;
The 8bit.ws cloud extends LLM features through its Satellite system, enabling serverless functions to harness AI's predictive power. Here’s how to exploit these capabilities in your cloud functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLAMA Satellite &amp;amp; its SDK&lt;/strong&gt;&lt;br&gt;
Our Cloud Computing Network provides LLM capabilities through what we call a Satellite. It does so by exporting llama.cpp capabilities to the Taubyte Virtual Machine, which powers Serverless Functions (or DFunctions, as per Taubyte's terminology). The source code for the Satellite can be found &lt;a href="https://github.com/samyfodil/taubyte-llama-satellite"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Satellites export low-level functions that aren't very intuitive to use directly. Fortunately, it's possible to address that with a user-friendly SDK. As of today, we offer a &lt;a href="https://go.dev/"&gt;Go&lt;/a&gt; SDK. The source code can be found &lt;a href="https://github.com/samyfodil/taubyte-llama-satellite/tree/main/sdk"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building a Predictive Function&lt;/strong&gt;&lt;br&gt;
Let’s construct a function that uses LLM to process prompts. &lt;/p&gt;

&lt;p&gt;Before proceeding, let's ensure you have a project and a DFunction ready to go. If not, please refer to &lt;a href="https://tau.how/guides/build/02-guide/02-create-a-dfunc/"&gt;"Create a Function"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you followed the steps from &lt;a href="https://tau.how/guides/build/02-guide/01-create-project/"&gt;Taubyte's Documentation&lt;/a&gt;, your basic function should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/taubyte/go-sdk/event"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PONG"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will transform this &lt;code&gt;ping&lt;/code&gt; function to a &lt;code&gt;predict&lt;/code&gt; function that takes a prompt from the POST request body and returns a prediction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incorporating LLM Predictions&lt;/strong&gt;&lt;br&gt;
Here's how to modify your function to perform LLM predictions with the LLAMA SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/taubyte/go-sdk/event"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/samyfodil/taubyte-llama-satellite/sdk"&lt;/span&gt;
    &lt;span class="s"&gt;"io"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTopK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTopP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0.86&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithBatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EOF&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;&lt;br&gt;
This function reads the POST body as the prompt for the LLM. It then requests a prediction and enters a loop to write each token received back to the HTTP response. We’ve used the &lt;code&gt;sdk.Predict&lt;/code&gt; method to send the prompt to the LLM and &lt;code&gt;p.Next&lt;/code&gt; to iterate over the tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploying Your Function&lt;/strong&gt;&lt;br&gt;
Once your function is ready, deploy it to the 8bit.ws cloud. Ensure your function's entry point and method are configured correctly to handle POST requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
By integrating LLM with WASM in the 8bit.ws cloud, we unlock the potential for applications that are not just reactive, but proactive and intelligent. As open-source initiatives, 8bit.ws and Taubyte provide fertile ground for innovation, inviting developers to build, share, and improve upon a collective vision for the future of cloud computing.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>llm</category>
      <category>go</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
