<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Michael Yuan - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Michael Yuan - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:23:56 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/michaelyuan/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Voice AI Agent Using Open-Source Tools ]]>
                </title>
                <description>
                    <![CDATA[ Voice is the next frontier of conversational AI. It is the most natural modality for people to chat and interact with another intelligent being. In the past year, frontier AI labs such as OpenAI, xAI, Anthropic, Meta, and Google have all released rea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-voice-ai-agent-using-open-source-tools/</link>
                <guid isPermaLink="false">68f7d890413573e1d65bb331</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ education ]]>
                    </category>
                
                    <category>
                        <![CDATA[ stem ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Voice ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agentic AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Open Source ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Tue, 21 Oct 2025 19:01:36 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761073279608/a73ce2cd-c95e-4f8b-b529-8774ce39a43f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Voice is the next frontier of conversational AI. It is the most natural modality for people to chat and interact with another intelligent being.</p>
<p>In the past year, frontier AI labs such as OpenAI, xAI, Anthropic, Meta, and Google have all released real-time voice services. Yet voice apps also have the highest requirements for latency, privacy, and customization. It’s difficult to have a one-size-fits-all voice AI solution.</p>
<p>In this article, we’ll explore how to use open-source technologies to create <a target="_blank" href="https://echokit.dev/">voice AI agents</a> that utilize your custom knowledge base, voice style, actions, fine-tuned AI models, and run on your own computer.</p>
<h2 id="heading-what-well-cover">What We’ll Cover:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-it-looks-like">What it Looks Like</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-two-voice-ai-approaches">Two Voice AI Approaches</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-voice-ai-orchestrator">The Voice AI Orchestrator</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-configure-an-asr">Configure an ASR</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-and-configure-a-vad">Run and configure a VAD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-configure-an-llm">Configure an LLM</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-configure-a-tts">Configure a TTS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-configure-mcp-and-actions">Configure MCP and actions</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-local-ai-with-llamaedge">Local AI With LlamaEdge</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You’ll need to have and know a few things to most effectively follow along with this tutorial:</p>
<ul>
<li><p>Access to a Linux-like system. Mac or Windows WSL suffice too.</p>
</li>
<li><p>Be comfortable with command line (CLI) tools.</p>
</li>
<li><p>Be able to run server applications on the Linux system.</p>
</li>
<li><p>Have/get free API keys from <a target="_blank" href="https://console.groq.com/keys">Groq</a> and <a target="_blank" href="https://elevenlabs.io/app/sign-in?redirect=%2Fapp%2Fdevelopers%2Fapi-keys">ElevenLabs</a>.</p>
</li>
<li><p>Optional: be able to compile and build Rust source code.</p>
</li>
<li><p>Optional: have/get an <a target="_blank" href="https://echokit.dev/echokit_diy.html">EchoKit device</a> or assemble your own.</p>
</li>
</ul>
<h2 id="heading-what-it-looks-like">What it Looks Like</h2>
<p>The key software component we will cover is the <a target="_blank" href="https://github.com/second-state/echokit_server">echokit_server</a> project. It is an open-source agent orchestrator for voice AI applications. That means it coordinates services such as LLMs, ASR, TTS, VAD, MCP, search, knowledge/vector databases, and others to generate intelligent voice responses from user prompts.</p>
<p>The EchoKit server provides a WebSocket interface that allows compatible clients to send and receive voice data to and from it. The <a target="_blank" href="https://github.com/second-state/echokit_box">echokit_box</a> project provides an ESP32-based firmware that can act as a client to collect audio from the user and play TTS-generated voice from the EchoKit server. You can see a couple of demos here. You can assemble your own EchoKit device or <a target="_blank" href="https://echokit.dev/echokit_diy.html">purchase one</a>.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/XroT7a0DLkw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Zy-rLT4EgZQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>Of course, you can also use a pure software client that conforms to the <a target="_blank" href="https://github.com/second-state/echokit_server">echokit_server</a> WebSocket interface. The project publishes a <a target="_blank" href="https://echokit.dev/chat/">JavaScript web page</a> that you can run locally to connect to your own EchoKit server as a reference.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Eyd9ToflccY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>In the rest of the article, I will discuss how it’s implemented and how to deploy the system for your own voice AI applications.</p>
<h2 id="heading-two-voice-ai-approaches">Two Voice AI Approaches</h2>
<p>When OpenAI released its “realtime voice” services in October 2024, the consensus was that voice AI required “end-to-end” AI models. Traditional LLMs take text as input and then respond in text. The voice end-to-end models take voice audio data as input and respond in voice audio data as well. The end-to-end models could reduce latency since the voice processing, understanding, and generation are done in a single step.</p>
<p>But an end-to-end model is very difficult to customize. For example, it’s impossible to add your own prompt and knowledge to the context for each LLM request, or to act on the LLM's thinking or tool-call responses, or to clone your own voice for the response.</p>
<p>The second approach is to use an “agent orchestration” service to tie together multiple AI models, using one model’s output as the input for the next model. This allows us to customize or select each model and manipulate or supplement the model input at every step.</p>
<ul>
<li><p>The VAD model is used to detect conversation turns in the user's speech. It determines when the user is finished speaking and is now expecting a response.</p>
</li>
<li><p>The ASR/STT model turns user speech into text.</p>
</li>
<li><p>The LLM model generates a text response, including MCP tool calls.</p>
</li>
<li><p>The TTS model turns the response text into voice.</p>
</li>
</ul>
<p>The issue with multi-model and multi-step orchestration is that it can be slow. A lot of optimizations are needed for this approach to work well. For example, a useful technique is to utilize streaming input and output wherever possible. This way, each model doesn’t have to wait for the complete response from the upstream model.</p>
<p>The <a target="_blank" href="https://github.com/second-state/echokit_server">EchoKit server</a> is a stream-everything, highly efficient AI model orchestrator. It is entirely written in Rust for stability, safety, and speed.</p>
<h2 id="heading-the-voice-ai-orchestrator">The Voice AI Orchestrator</h2>
<p>The EchoKit server project is an open-source AI service orchestrator focused on real-time voice use cases. It starts up a WebSocket server that listens for streaming audio input and returns streaming audio responses.</p>
<p>You can build the <a target="_blank" href="https://github.com/second-state/echokit_server">echokit_server</a> project yourself using the Rust toolchain. Or, you can simply download the pre-built binary for your computer.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># for x86 / AMD64 CPUs</span>
curl -LO https://github.com/second-state/echokit_server/releases/download/v0.1.0/echokit_server-v0.1.0-x86_64-unknown-linux-gnu.tar.gz
unzip echokit_server-v0.1.0-x86_64-unknown-linux-gnu.tar.gz

<span class="hljs-comment"># for arm64 CPUs</span>
curl -LO https://github.com/second-state/echokit_server/releases/download/v0.1.0/echokit_server-v0.1.0-aarch64-unknown-linux-gnu.tar.gz
unzip echokit_server-v0.1.0-aarch64-unknown-linux-gnu.tar.gz
</code></pre>
<p>Then, run it as follows:</p>
<pre><code class="lang-bash">nohup ./echokit_server &amp;
</code></pre>
<p>It reads the <code>config.toml</code> file from the current directory. At the top of the file, you can configure the port on which the WebSocket server listens. You can also specify a WAV file that is downloaded to the connected <a target="_blank" href="https://echokit.dev/echokit_diy.html">EchoKit client device</a> as a welcome message.</p>
<pre><code class="lang-ini"><span class="hljs-attr">addr</span> = <span class="hljs-string">"0.0.0.0:8000"</span>
<span class="hljs-attr">hello_wav</span> = <span class="hljs-string">"hello.wav"</span>
</code></pre>
<h3 id="heading-configure-an-asr">Configure an ASR</h3>
<p>When the EchoKit server receives the user's voice data, it first sends the data to an ASR service to convert it into text.</p>
<p>There are many compelling ASR models available today. The EchoKit server can work with any OpenAI-compatible API providers, such as OpenAI itself, x.ai, OpenRouter, and Groq.</p>
<p>In our example, we use Groq’s Whisper ASR service. Whisper is a state-of-the-art ASR model released by OpenAI. Groq provides specialized hardware chips to run it very fast. You will first get <a target="_blank" href="https://console.groq.com/keys">a free API key from Groq</a>. Then, configure the ASR service as follows. Notice the “prompt” for the Whisper model. It is a tried-and-true prompt to reduce hallucination of the Whisper model.</p>
<pre><code class="lang-ini"><span class="hljs-section">[asr]</span>
<span class="hljs-attr">url</span> = <span class="hljs-string">"https://api.groq.com/openai/v1/audio/transcriptions"</span>
<span class="hljs-attr">api_key</span> = <span class="hljs-string">"gsk_XYZ"</span>
<span class="hljs-attr">model</span> = <span class="hljs-string">"whisper-large-v3"</span>
<span class="hljs-attr">lang</span> = <span class="hljs-string">"en"</span>
<span class="hljs-attr">prompt</span> = <span class="hljs-string">"Hello\n你好\n(noise)\n(bgm)\n(silence)\n"</span>
</code></pre>
<h3 id="heading-run-and-configure-a-vad">Run and configure a VAD</h3>
<p>In order to carry out a voice conversation, participants must detect each other's intentions and speak only when a turn arises. VAD (Voice Activity Detection) is a specialized AI model used to detect activities and, in particular, when the speaker has finished and expects an answer.</p>
<p>In EchoKit, we have VAD detection on both the device and the server.</p>
<ul>
<li><p>Device-side VAD: It detects human language. The device ignores background noise, music, keyboard sounds, and dog barking. It only sends human voice to the server.</p>
</li>
<li><p>Server-side VAD: It processes the audio stream in 100ms (0.1s) chunks. Once it detects that the speaker has finished, it sends all transcribed text to the LLM and starts waiting for the LLM’s response stream.</p>
</li>
</ul>
<p>The server-side VAD is optional, since the device-side VAD can also generate “conversation turn” signals. But due to the limited computing resources on the device, adding the server-side VAD can dramatically improve the overall VAD performance.</p>
<p>We’re porting the popular <a target="_blank" href="https://github.com/snakers4/silero-vad">Silero VAD</a> project from Python to Rust, and creating the <a target="_blank" href="https://github.com/second-state/silero_vad_server">silero_vad_server</a> project. Build the project <a target="_blank" href="https://github.com/second-state/silero_vad_server?tab=readme-ov-file#build-the-api-server">as instructed</a>. You can start the VAD server on your EchoKit server’s port 9094 as follows:</p>
<pre><code class="lang-bash">VAD_LISTEN=0.0.0.0:9094 nohup target/release/silero_vad_server &amp;
</code></pre>
<p>You might be wondering: why port to Rust? While many AI projects are written in Python for ease of development, Rust applications are often much lighter, faster, and safer at deployment. So, we’ll leverage AI tools like <a target="_blank" href="https://github.com/cardea-mcp/RustCoder">RustCoder</a> to port as much Python code as possible to Rust. The EchoKit software stack is largely written in Rust.</p>
<p>The VAD server is a WebSocket service that listens on port 9094. As we discussed, the EchoKit server will stream audio to this WebSocket and stop the ASR when a conversation turn is detected. Therefore, we’ll add the VAD service to the EchoKit server’s ASR config section in <code>config.toml</code>.</p>
<pre><code class="lang-ini"><span class="hljs-section">[asr]</span>
<span class="hljs-attr">url</span> = <span class="hljs-string">"https://api.groq.com/openai/v1/audio/transcriptions"</span>
<span class="hljs-attr">api_key</span> = <span class="hljs-string">"gsk_XYZ"</span>
<span class="hljs-attr">model</span> = <span class="hljs-string">"whisper-large-v3"</span>
<span class="hljs-attr">lang</span> = <span class="hljs-string">"en"</span>
<span class="hljs-attr">prompt</span> = <span class="hljs-string">"Hello\n你好\n(noise)\n(bgm)\n(silence)\n"</span>
<span class="hljs-attr">vad_realtime_url</span> = <span class="hljs-string">"ws://localhost:9094/v1/audio/realtime_vad"</span>
</code></pre>
<h3 id="heading-configure-an-llm">Configure an LLM</h3>
<p>Once the ASR service transcribes the user's voice into text, the next step in the pipeline is the LLM (Large Language Model). It’s the AI service that actually “thinks” and generates an answer in text.</p>
<p>Again, the EchoKit server can work with any OpenAI-compatible API providers for LLMs, such as OpenAI itself, x.ai, OpenRouter, and Groq. Since the voice service is highly sensitive to speed, we’ll choose Groq again. Groq supports a number of open-source LLMs. We’ll choose the <code>gpt-oss-20b</code> model released by OpenAI.</p>
<pre><code class="lang-ini"><span class="hljs-section">[llm]</span>
<span class="hljs-attr">llm_chat_url</span> = <span class="hljs-string">"https://api.groq.com/openai/v1/chat/completions"</span>
<span class="hljs-attr">api_key</span> = <span class="hljs-string">"gsk_XYZ"</span>
<span class="hljs-attr">model</span> = <span class="hljs-string">"openai/gpt-oss-20b"</span>
<span class="hljs-attr">history</span> = <span class="hljs-number">20</span>
</code></pre>
<p>The “history” field indicates how many messages should be kept in the context. Another crucial feature of an LLM application is the “system prompt,” where you instruct the LLM how it should “behave.” You can specify the system prompt in the EchoKit server config as well.</p>
<pre><code class="lang-ini"><span class="hljs-section">[[llm.sys_prompts]]</span>
<span class="hljs-attr">role</span> = <span class="hljs-string">"system"</span>
<span class="hljs-attr">content</span> = <span class="hljs-string">"""
You are a comedian. Engage in lighthearted and humorous conversation with the user. Tell jokes when appropriate.

"""</span>
</code></pre>
<p>Since Groq is very fast, it can process very large system prompts in under one second. You can add a lot more context and instructions to the system prompt. For example, you can give the application “knowledge” about a specific field by putting entire books into the system prompt.</p>
<h3 id="heading-configure-a-tts">Configure a TTS</h3>
<p>Finally, once the LLM generates a text response, the EchoKit server will call a TTS (text to speech) service to convert the text into voice and stream it back to the client device.</p>
<p>While Groq has a TTS service, it’s not particularly compelling. ElevenLabs is a leading TTS provider that offers hundreds of voice characters. It can express emotions and supports easy voice cloning. In the config below, you’ll put in your <a target="_blank" href="https://elevenlabs.io/app/sign-in?redirect=%2Fapp%2Fdevelopers%2Fapi-keys">ElevenLabs API key</a> and select a voice.</p>
<pre><code class="lang-ini"><span class="hljs-section">[tts]</span>
<span class="hljs-attr">platform</span> = <span class="hljs-string">"Elevenlabs"</span>
<span class="hljs-attr">token</span> = <span class="hljs-string">"sk_xyz"</span>
<span class="hljs-attr">voice</span> = <span class="hljs-string">"VOICE-ID-ABCD"</span>
</code></pre>
<p>The ElevenLabs TTS models and API services are all great, but they are not open-source. A very compelling open-source TTS, known as GPT-SoVITS, is also available.</p>
<p>You can port GPT-SoVITS from Python to Rust and create an open-source API server project called <a target="_blank" href="https://github.com/second-state/gsv_tts">gsv_tts</a>. It allows easy cloning of any voice. You can run a <a target="_blank" href="https://github.com/second-state/gsv_tts">gsv_tts</a> API server by following its instructions. Then, you can configure the EchoKit server to stream text to it and receive streaming audio from it.</p>
<pre><code class="lang-ini"><span class="hljs-section">[tts]</span>
<span class="hljs-attr">platform</span> = <span class="hljs-string">"StreamGSV"</span>
<span class="hljs-attr">url</span> = <span class="hljs-string">"http://gsv_tts.server:port/v1/audio/stream_speech"</span>
<span class="hljs-attr">speaker</span> = <span class="hljs-string">"michael"</span>
</code></pre>
<h3 id="heading-configure-mcp-and-actions">Configure MCP and actions</h3>
<p>Of course, an “AI agent” is not just about chatting. It is about performing actions on specific tasks. For example, the <a target="_blank" href="https://www.youtube.com/watch?v=Zy-rLT4EgZQ">“US civics test prep”</a> use case, which I shared as an example video at the beginning of this article, requires the agent to get exam questions from a database, and then generate responses that guide the user toward the official answer. This is accomplished using LLM tools and actions.</p>
<ul>
<li><p>The LLM detects that the user is requesting a new question.</p>
</li>
<li><p>Instead of responding in natural language, it responds with a JSON structure that instructs the agent to "get a new question and answer."</p>
</li>
<li><p>The EchoKit server intercepts this JSON response and retrieves the question and answer from a database.</p>
</li>
<li><p>The EchoKit server sends the question and answer back to the LLM.</p>
</li>
<li><p>The LLM formulates a natural language response based on the question and answer.</p>
</li>
<li><p>The EchoKit server generates a voice response using its TTS service.</p>
</li>
</ul>
<p>As you can see, the EchoKit server needs to perform a few extra steps behind the scenes before it responds in voice. The EchoKit server leverages the MCP protocol for this. The function to look up questions and answers is provided by an open-source MCP server called <a target="_blank" href="https://github.com/cardea-mcp/ExamPrepAgent">ExamPrepAgent</a>.</p>
<p>The MCP protocol standardizes the tools and functions for LLMs to call. There are many MCP servers available for all kinds of different tasks. ExamPrepAgent is just one of them.</p>
<p>We are running this MCP server on port 8003. With the MCP server up and running, you only need to add the following configuration to EchoKit server’s <code>config.toml</code>.</p>
<pre><code class="lang-ini"><span class="hljs-section">[[llm.mcp_server]]</span>
<span class="hljs-attr">server</span> = <span class="hljs-string">"http://localhost:8003/mcp"</span>
<span class="hljs-attr">type</span> = <span class="hljs-string">"http_streamable"</span>
</code></pre>
<p>With MCP integration, the EchoKit AI agent can now perform actions. It can call APIs to send messages, make payments, or even turn electronic devices on or off.</p>
<h2 id="heading-local-ai-with-llamaedge">Local AI With LlamaEdge</h2>
<p>You’ve now seen the open-source EchoKit device working with the open-source EchoKit server to understand and respond to users in voice. But the AI models we use, while also open-source, run on commercial cloud providers. Can we run AI models using open-source technologies at home?</p>
<p><a target="_blank" href="https://github.com/LlamaEdge/LlamaEdge">LlamaEdge</a> is an open-source, cross-platform API server for AI models. It <a target="_blank" href="https://llamaedge.com/docs/ai-models/">supports many mainstream LLM, ASR, and TTS models</a> across Linux, Mac, Windows, and many CPU/GPU architectures. It’s perfect for running AI models on home or office computers. It also provides OpenAI-compatible API endpoints, which makes them very easy to integrate into the EchoKit server.</p>
<p>To install LlamaEdge and its dependencies, run the following shell command. It will detect your hardware and install the appropriate software that can fully take advantage of your GPUs (if any).</p>
<pre><code class="lang-bash">curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install_v2.sh | bash -s
</code></pre>
<p>Then, download an open-source LLM model. I am using Google's Gemma model as an example.</p>
<pre><code class="lang-bash">curl -LO https://huggingface.co/second-state/gemma-3-4b-it-GGUF/resolve/main/gemma-3-4b-it-Q5_K_M.gguf
</code></pre>
<p>Download the cross-platform LlamaEdge API server.</p>
<pre><code class="lang-bash">curl -LO https://github.com/second-state/LlamaEdge/releases/latest/download/llama-api-server.wasm
</code></pre>
<p>Start an LLamaEdge API server with the Google Gemma LLM model. by default, it listens on localhost port 8080.</p>
<pre><code class="lang-bash">wasmedge --dir .:. --nn-preload default:GGML:AUTO:gemma-3-4b-it-Q5_K_M.gguf llama-api-server.wasm -p gemma-3
</code></pre>
<p>Test the OpenAI compatible API on that server.</p>
<pre><code class="lang-bash">curl -X POST http://localhost:8080/v1/chat/completions \
  -H <span class="hljs-string">'accept: application/json'</span> \
  -H <span class="hljs-string">'Content-Type: application/json'</span> \
  -d <span class="hljs-string">'{"messages":[{"role":"system", "content": "You are a helpful assistant. Try to be as brief as possible."}, {"role":"user", "content": "Where is the capital of Texas?"}]}'</span>
</code></pre>
<p>Now, you can add this local LLM service to your EchoKit server configuration.</p>
<pre><code class="lang-ini"><span class="hljs-section">[llm]</span>
<span class="hljs-attr">llm_chat_url</span> = <span class="hljs-string">"http://localhost:8080/v1/chat/completions"</span>
<span class="hljs-attr">api_key</span> = <span class="hljs-string">"NONE"</span>
<span class="hljs-attr">model</span> = <span class="hljs-string">"default"</span>
<span class="hljs-attr">history</span> = <span class="hljs-number">20</span>
</code></pre>
<p>The LlamaEdge project supports more than LLMs. It runs the <a target="_blank" href="https://github.com/LlamaEdge/whisper-api-server">Whisper ASR model</a> and the <a target="_blank" href="https://github.com/LlamaEdge/tts-api-server">Piper TTS model</a> as OpenAI-compatible API servers as well.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The voice AI agent software stack is complex and deep. EchoKit is an open-source platform that ties together and coordinates all those components. It provides a good vantage point for us to learn about the entire stack.</p>
<p>I can’t wait to see what you build!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Serverless ChatGPT App in 10 Minutes ]]>
                </title>
                <description>
                    <![CDATA[ Since OpenAI released an official API for ChatGPT in March 2023, many developers and entrepreneurs are interested in integrating it into their own business operations. But some significant barriers remain that make it difficult for them to do this: ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-serverless-chatgpt-app/</link>
                <guid isPermaLink="false">66d4604433b83c4378a51806</guid>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #chatbots ]]>
                    </category>
                
                    <category>
                        <![CDATA[ serverless ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Mon, 20 Mar 2023 16:52:42 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/c0fd422e-f234-49e2-85a6-24f91b0b9991-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Since OpenAI <a target="_blank" href="https://openai.com/blog/introducing-chatgpt-and-whisper-apis">released an official API for ChatGPT</a> in March 2023, many developers and entrepreneurs are interested in integrating it into their own business operations.</p>
<p>But some significant barriers remain that make it difficult for them to do this:</p>
<ul>
<li><p>OpenAI provides <a target="_blank" href="https://platform.openai.com/docs/guides/chat">a simple stateless API</a> for ChatGPT. The developer needs to keep track of the history and context of each conversation in a cache or database managed by the application. The developer also needs to manage and safeguard the API keys. There is a lot of boilerplate code unrelated to the application’s business logic.</p>
</li>
<li><p>The “natural” UI for the ChatGPT API application is a threaded chat. But it is difficult to create a “chat UI” in a traditional web or app framework. In fact, the most commonly used chat UI already exists in messaging apps like Slack, Discord, and even forums (for example, GitHub Discussions). We need a simple way to connect ChatGPT API responses to an existing messaging service.</p>
</li>
</ul>
<p>In this article, I will show you how to create a serverless GitHub bot. The bot allows GitHub users to chat with ChatGPT and each other in GitHub Issues. You can <a target="_blank" href="https://github.com/second-state/chat-with-chatgpt/issues/new">try it by asking a question</a>, or <a target="_blank" href="https://github.com/second-state/chat-with-chatgpt/issues">joining another conversation thread</a> by leaving a comment. In other words, this project uses GitHub Issues’ threaded messages UI as its own chat UI.</p>
<p><img src="https://i.imgur.com/7eWhQ8I.png" alt="Image" width="1842" height="1862" loading="lazy"></p>
<p><em>Figure 1. Learning Rust with ChatGPT. see</em> <a target="_blank" href="https://github.com/second-state/chat-with-chatgpt/issues/31"><em>https://github.com/second-state/chat-with-chatgpt/issues/31</em></a></p>
<p>The bot is a serverless function written in Rust. Just fork the example, deploy your fork on <a target="_blank" href="https://www.freecodecamp.org/news/p/dfeeb7b1-d632-448e-97b3-9fcd7df30bce/flows.network">flows.network</a>, and configure it to interact with your own GitHub repos and OpenAI keys. You will have a fully functional GitHub bot in 10 minutes. There is no need to set up a web server, or a webhook for GitHub API, or a cache / database server.</p>
<h2 id="heading-how-to-fork-the-template-repo">How to Fork the Template Repo</h2>
<p>First, <a target="_blank" href="https://github.com/flows-network/chatgpt-github-app">fork this template repo from GitHub</a>.</p>
<p>The <a target="_blank" href="https://github.com/flows-network/chatgpt-github-app/blob/main/src/lib.rs"><code>src/lib.rs</code></a> file contains the bot application (also known as the flow function). The <code>run()</code> function is called upon starting up. It listens for <code>issue_comment</code> and <code>issues</code> events from the GitHub repo <a target="_blank" href="https://github.com/second-state/chat-with-chatgpt"><code>owner/repo</code></a>. Those events are emitted when a new issue comment or a new issue is created in the repo.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[no_mangle]</span>
<span class="hljs-meta">#[tokio::main(flavor = <span class="hljs-meta-string">"current_thread"</span>)]</span>
<span class="hljs-keyword">pub</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">run</span></span>() {
    <span class="hljs-comment">// Setup variables for</span>
    <span class="hljs-comment">//   ower: GitHub org to install the bot</span>
    <span class="hljs-comment">//   repo: GitHub repo to install the bot</span>
    <span class="hljs-comment">//   openai_key_name: Name for your OpenAI API key</span>
    <span class="hljs-comment">// All the values can be set in the source code or as env vars</span>

    listen_to_event(&amp;owner, &amp;repo, <span class="hljs-built_in">vec!</span>[<span class="hljs-string">"issue_comment"</span>, <span class="hljs-string">"issues"</span>], |payload| {
        handler(&amp;owner, &amp;repo, &amp;openai_key_name, payload)
    })
    .<span class="hljs-keyword">await</span>;
}
</code></pre>
<p>The <code>handler()</code> function processes the events received by <code>listen_to_event()</code>. If the event is a new comment in an issue, the bot calls OpenAI's ChatGPT API to add the comment text into an existing conversation identified by the <code>issue.number</code>. It receives a response from ChatGPT, and adds a comment in the issue.</p>
<p>The flow function here automatically and transparently manages the conversation history with the ChatGPT API in a local storage. The OpenAI API key is also stored in the local storage so that instead of putting the secret text in the source code, the key can be identified by a string name in <code>openai_key_name</code>.</p>
<pre><code class="lang-rust">EventPayload::IssueCommentEvent(e) =&gt; {
    <span class="hljs-keyword">if</span> e.comment.user.r#<span class="hljs-class"><span class="hljs-keyword">type</span> != "<span class="hljs-title">Bot</span></span><span class="hljs-string">" {
        if let Some(b) = e.comment.body {
            if let Some(r) = chat_completion (
                    openai_key_name,
                    &amp;format!("</span>issue#{}<span class="hljs-string">", e.issue.number),
                    &amp;b,
                    &amp;ChatOptions::default(),
            ) {
                if let Err(e) = issues.create_comment(e.issue.number, r.choice).await {
                    write_error_log!(e.to_string());
                }
            }
        }
    }
}</span>
</code></pre>
<p>If the event is a new issue, the flow function creates a new conversation identified by <code>issue.number</code>, and requests a response from ChatGPT.</p>
<pre><code class="lang-rust">EventPayload::IssuesEvent(e) =&gt; {
    <span class="hljs-keyword">if</span> e.action == IssuesEventAction::Closed {
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> title = e.issue.title;
    <span class="hljs-keyword">let</span> body = e.issue.body.unwrap_or(<span class="hljs-string">""</span>.to_string());
    <span class="hljs-keyword">let</span> q = title + <span class="hljs-string">"\n"</span> + &amp;body;
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-literal">Some</span>(r) = chat_completion (
            openai_key_name,
            &amp;<span class="hljs-built_in">format!</span>(<span class="hljs-string">"issue#{}"</span>, e.issue.number),
            &amp;q,
            &amp;ChatOptions::default(),
    ) {
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-literal">Err</span>(e) = issues.create_comment(e.issue.number, r.choice).<span class="hljs-keyword">await</span> {
            write_error_log!(e.to_string());
        }
    }
}
</code></pre>
<h2 id="heading-how-to-deploy-the-serverless-flow-function">How to Deploy the Serverless Flow Function</h2>
<p>As we can see, the flow function code calls SDK APIs to perform complex operations. For example,</p>
<ul>
<li><p>The <code>listen_to_event()</code> function registers a webhook URL through GitHub API so that the <code>handler()</code> function will be called when certain events occur in GitHub.</p>
</li>
<li><p>The <code>chat_completion()</code> function calls the ChatGPT API with the named API key and past history / context of the specified conversation. The API key and conversation history are stored in a Redis cache.</p>
</li>
</ul>
<p>The webhook server and the Redis cache are both external services the SDK depends on. That means the flow function must run inside a managed host environment that provides such external services. <a target="_blank" href="https://flows.network/">Flows.network</a> is a PaaS (Platform as a Service) host for the flow function SDKs.</p>
<p>In order to deploy the flow function on flows.network, you simply need to import its source code to the PaaS.</p>
<p>First, sign into flows.network from your GitHub account. Import your forked GitHub repo that contains the flow function source code and choose "With Environment Variables".</p>
<p>Note that this is NOT the GitHub repo where you want to deploy the bot. This is the repo for your forked flow function source code.</p>
<p><img src="https://i.imgur.com/CH1nUf8.png" alt="Image" width="1362" height="1182" loading="lazy"></p>
<p><em>Figure 2. Import the GitHub repo you forked from the flow function template into flows.network.</em></p>
<p>Set the environment variables to point the flow function to the OpenAI API key name (<code>open_ai_key</code>) and GitHub repo (<code>owner</code> and <code>repo</code>).</p>
<p>The GitHub <code>owner</code> and <code>repo</code> variables here point to the GitHub repo where you want to deploy the bot, NOT the repo for the flow function source code.</p>
<p><img src="https://i.imgur.com/5gcTKMv.png" alt="Image" width="726" height="527" loading="lazy"></p>
<p><em>Figure 3. Set the environment variables for the GitHub repo where you want to deploy the bot, as well as the OpenAI API key name.</em></p>
<p>Flows.network will fetch the source code and build the Rust source code into Wasm bytecode using the standard <code>cargo</code> toolchain. It will then run the Wasm flow function in the <a target="_blank" href="https://github.com/WasmEdge/WasmEdge">WasmEdge Runtime</a>.</p>
<h2 id="heading-how-to-connect-the-flow-function-to-github-and-openai">How to Connect the Flow Function to GitHub and OpenAI</h2>
<p>While the flow function requires connections to the OpenAI and GitHub APIs, the source code has no hardcoded API keys, access tokens, or OAUTH logic. The flows function SDKs have made it easy and safe for developers to interact with external SaaS API services.</p>
<p>Flows.network discovers that the flow function requires connections to the OpenAI and GitHub APIs. It presents UI workflows for the developers to:</p>
<ul>
<li><p>Log into GitHub, authorize access to events, and register the flow function as the webhook for receiving those events.</p>
</li>
<li><p>Associate an OpenAI API key with the name <code>openai_key_name</code>.</p>
</li>
</ul>
<p><img src="https://i.imgur.com/CpLDrub.png" alt="Image" width="1393" height="484" loading="lazy"></p>
<p><em>Figure 4. The external services required by the flow function are connected and turned green.</em></p>
<p>Once the external SaaS APIs are connected and authorized, they turn green on the flow function dashboard. The flow function will now receive the events it <code>listen_to_event()</code> for. It will also get transparent access to Redis for the named OpenAI API key and the cached conversation context to support the <code>chat_completion()</code> SDK function.</p>
<h2 id="heading-whats-next">What's next</h2>
<p>The GitHub bot is just one of many bot types the flows.network can support. By connecting the flow function to a Slack channel, you can get ChatGPT to participate in your group discussion. Here is an example of a Slack-based ChatGPT bot.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/flows-network/collaborative-chat">https://github.com/flows-network/collaborative-chat</a></div>
<p> </p>
<p><img src="https://i.imgur.com/voB27bj.png" alt="Image" width="1446" height="842" loading="lazy"></p>
<p><em>Figure 5. The Slack ChatGPT bot.</em></p>
<p>Another example is to have ChatGPT answering legal questions in a Slack channel. The flow function prepends the legal question with a prompt.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/flows-network/robo-lawyer">https://github.com/flows-network/robo-lawyer</a></div>
<p> </p>
<p><img src="https://i.imgur.com/afDM5im.png" alt="Image" width="1544" height="978" loading="lazy"></p>
<p><em>Figure 6. The Slack robo lawyer bot.</em></p>
<p>Besides GitHub and Slack, there are many SaaS products you can integrate into flows.network through their APIs.</p>
<p>While the example flow functions are written in Rust, we aim to support JavaScript-based flow function SDKs. In another word, platform SDK functions such as <code>listen_to_event()</code> and <code>chat_completion()</code> will have a JavaScript version. The JavaScript flow function runs inside the <a target="_blank" href="https://github.com/WasmEdge/WasmEdge">WasmEdge Runtime</a> on the flows.network platform through the <a target="_blank" href="https://wasmedge.org/docs/develop/javascript/intro">WasmEdge-QuickJS</a> module.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Edge Cloud Microservices – How to Build High Performance & Secure Apps with WasmEdge and Rust ]]>
                </title>
                <description>
                    <![CDATA[ The edge cloud allows developers to deploy microservices (that is, fine-grained web services) close to their users. This gives them a better user experience (and very fast response times), security, and high availability. It also leverages local or e... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/edge-cloud-microservices-with-wasmedge-and-rust/</link>
                <guid isPermaLink="false">66d460488812486a37369d13</guid>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Fri, 16 Sep 2022 17:43:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/richard-r-schunemann-DD3VNthK_Kw-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The edge cloud allows developers to deploy microservices (that is, fine-grained web services) close to their users. This gives them a better user experience (and very fast response times), security, and high availability.</p>
<p>It also leverages local or even private data centers, CDN networks, and telecomm data centers (for example 5G MECs) to provide compute services.</p>
<p>Successful examples of edge clouds include Cloudflare, Fastly, Akamai, fly.io, Vercel, Netlify, and many others.</p>
<p>But the edge cloud is also a resource-constrained environment compared with big public clouds. If the edge microservices themselves are slow or bloated or insecure, they will defeat the whole purpose of deploying on the edge cloud.</p>
<p>In this article, I will show you how to create lightweight and high-performance web services in the <a target="_blank" href="https://github.com/WasmEdge">WebAssembly sandbox</a>, and then deploy them for free on edge cloud provider <a target="_blank" href="http://fly.io">fly.io</a>.</p>
<p><a target="_blank" href="http://Fly.io">Fly.io</a> is a leading provider of VM services on the edge cloud. It has edge data centers around the world. The <a target="_blank" href="http://Fly.io">fly.io</a> VMs support app servers, databases, and in our case, lightweight runtimes for microservices.</p>
<p>I will use the <a target="_blank" href="https://github.com/WasmEdge/WasmEdge">WasmEdge Runtime</a> as the security sandbox for those microservices. WasmEdge is a WebAssembly runtime specifically optimized for cloud-native services.</p>
<p>We will package the microservice application, written in Rust or JavaScript, in <a target="_blank" href="https://hub.docker.com/u/wasmedge">WasmEdge-based Docker images</a>.</p>
<p>There are several compelling advantages to this approach:</p>
<ul>
<li><p>WasmEdge runs sandboxed applications at near-native speed. According to a peer-reviewed study, WasmEdge runs Rust programs at nearly the same speed as Linux runs native machine code.</p>
</li>
<li><p>WasmEdge is a highly secure runtime. It protects your app against both external and internal threats.</p>
</li>
<li><p>The attack surface of the WasmEdge runtime is dramatically reduced from a regular Linux OS runtime.</p>
</li>
<li><p>The risk of software supply chain attack is greatly reduced since the WebAssembly sandbox only has access to explicitly declared capabilities.</p>
</li>
<li><p>WasmEdge provides a complete and portable application runtime environment at a memory footprint that is only 1/10 of a standard Linux OS runtime image.</p>
</li>
<li><p>The WasmEdge runtime is cross-platform. That means the development and deployment of machines do not have to be the same. And once you created a WasmEdge application, you can deploy it to anywhere WasmEdge is supported including <a target="_blank" href="http://fly.io">fly.io</a> infrastructure.</p>
</li>
</ul>
<p>The performance advantages are amplified if the application is complex. For example, a WasmEdge AI inference application would NOT require a Python install. A WasmEdge node.js application would NOT require a Node.js and v8 install.</p>
<p>In the rest of this article, I will demonstrate how to run:</p>
<ul>
<li><p>an async HTTP server (in Rust)</p>
</li>
<li><p>a very fast image classification web service (in Rust), and</p>
</li>
<li><p>a node.JS web server</p>
</li>
<li><p>stateful microservices with database connections</p>
</li>
</ul>
<p>All of them run fast and securely in WasmEdge while consuming 1/10 of the resources required by regular Linux containers.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>First, if you already have Docker tools installed on your system, that's great. If not, please follow <a target="_blank" href="https://www.freecodecamp.org/news/the-docker-handbook/">the first section of this handbook</a> to install Docker now. Then we will use online installers to install WasmEdge, Rust, and the <code>flyctl</code> tool for <a target="_blank" href="http://fly.io">fly.io</a>.</p>
<p>Install WasmEdge. <a target="_blank" href="https://wasmedge.org/book/en/start/install.html">See details here</a>.</p>
<pre><code class="lang-bash">curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -e all
</code></pre>
<p>Install Rust. <a target="_blank" href="https://www.rust-lang.org/tools/install">See details here</a>.</p>
<pre><code class="lang-bash">curl --proto <span class="hljs-string">'=https'</span> --tlsv1.2 -sSf https://sh.rustup.rs | sh
</code></pre>
<p>Install the <code>flyctl</code> tool for <a target="_blank" href="http://fly.io">fly.io</a>. <a target="_blank" href="https://fly.io/docs/hands-on/install-flyctl/">See details here</a>.</p>
<pre><code class="lang-bash">curl -L https://fly.io/install.sh | sh
</code></pre>
<p>Once you installed <code>flyctl</code>, follow the instructions to <a target="_blank" href="https://fly.io/docs/hands-on/sign-up/">sign up for a free account</a> at <a target="_blank" href="http://fly.io">fly.io</a>. You are now ready to deploy web services on the edge cloud!</p>
<h2 id="heading-a-simple-microservice-in-rust">A Simple Microservice in Rust</h2>
<p>Our first example is a simple HTTP service written in Rust. It demonstrates a modern web application that can be extended to support arbitrarily complex business logic.</p>
<p>Based on the popular tokio and hyper crates, this microservice is fast, async (non-blocking), and very easy for developers to create.</p>
<p>The fully statically linked WasmEdge image is only 4MB as opposed to 40MB for a base Linux image. That is sufficient to run an async HTTP service written in Rust’s tokio and hyper frameworks.</p>
<p>Run the following two CLI commands to create and then deploy a <a target="_blank" href="http://fly.io">fly.io</a> app from our slim Docker image for WasmEdge.</p>
<pre><code class="lang-bash">$ flyctl launch --image juntaoyuan/flyio-echo
$ flyctl deploy
</code></pre>
<p>That’s it! You can use the curl command to test whether the deployed web service actually works. It echoes back whatever data you post to it.</p>
<pre><code class="lang-bash">$ curl https://proud-sunset-3795.fly.dev/<span class="hljs-built_in">echo</span> -d <span class="hljs-string">"Hello WasmEdge on fly.io!"</span>
Hello WasmEdge on fly.io!
</code></pre>
<p>The Dockerfile for the <code>juntaoyuan/flyio-echo</code> Docker image contains the complete package of the WasmEdge runtime and the custom web application <code>wasmedge_hyper_server.wasm</code>.</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> wasmedge/slim-runtime:<span class="hljs-number">0.11</span>.<span class="hljs-number">0</span>
<span class="hljs-keyword">ADD</span><span class="bash"> wasmedge_hyper_server.wasm /</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"wasmedge"</span>, <span class="hljs-string">"--dir"</span>, <span class="hljs-string">".:/"</span>, <span class="hljs-string">"/wasmedge_hyper_server.wasm"</span>]</span>
</code></pre>
<p>The Rust source code project to build the <code>wasmedge_hyper_server.wasm</code> application <a target="_blank" href="https://github.com/WasmEdge/wasmedge_hyper_demo/tree/main/server">is available on GitHub</a>. It uses the tokio API to start an HTTP server.</p>
<p>When the server receives a request, it delegates to the <code>echo()</code> function to process the request asynchronously. That allows the microservice to accept and handle multiple concurrent HTTP requests.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[tokio::main(flavor = <span class="hljs-meta-string">"current_thread"</span>)]</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() -&gt; <span class="hljs-built_in">Result</span>&lt;(), <span class="hljs-built_in">Box</span>&lt;<span class="hljs-keyword">dyn</span> std::error::Error + <span class="hljs-built_in">Send</span> + <span class="hljs-built_in">Sync</span>&gt;&gt; {
    <span class="hljs-keyword">let</span> addr = SocketAddr::from(([<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], <span class="hljs-number">8080</span>));

    <span class="hljs-keyword">let</span> listener = TcpListener::bind(addr).<span class="hljs-keyword">await</span>?;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"Listening on http://{}"</span>, addr);
    <span class="hljs-keyword">loop</span> {
        <span class="hljs-keyword">let</span> (stream, _) = listener.accept().<span class="hljs-keyword">await</span>?;

        tokio::task::spawn(<span class="hljs-keyword">async</span> <span class="hljs-keyword">move</span> {
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-literal">Err</span>(err) = Http::new().serve_connection(stream, service_fn(echo)).<span class="hljs-keyword">await</span> {
                <span class="hljs-built_in">println!</span>(<span class="hljs-string">"Error serving connection: {:?}"</span>, err);
            }
        });
    }
}
</code></pre>
<p>The asynchronous <code>echo()</code> function is as follows. It utilizes the HTTP API provided by hyper to parse the request and generate the response. Here, the response is simply the request data body.</p>
<pre><code class="lang-rust"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">echo</span></span>(req: Request&lt;Body&gt;) -&gt; <span class="hljs-built_in">Result</span>&lt;Response&lt;Body&gt;, hyper::Error&gt; {
    <span class="hljs-keyword">match</span> (req.method(), req.uri().path()) {
        ... ...
        (&amp;Method::POST, <span class="hljs-string">"/echo"</span>) =&gt; <span class="hljs-literal">Ok</span>(Response::new(req.into_body())),
        ... ...

        <span class="hljs-comment">// Return the 404 Not Found for other routes.</span>
        _ =&gt; {
            <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            <span class="hljs-literal">Ok</span>(not_found)
        }
    }
}
</code></pre>
<p>Now let's add to the basic microservice to do something impressive!</p>
<h2 id="heading-an-ai-inference-microservice-in-rust">An AI Inference Microservice in Rust</h2>
<p>In this example, we will create a web service for image classification. It processes an uploaded image through a Tensorflow Lite model.</p>
<p>Instead of creating a complex (and bloated) Python program, we will use WasmEdge’s Rust API to access Tensorflow, which runs the inference task at full native machine code speed (for example, utilizing the GPU hardware if available).</p>
<p>Through the WASI-NN standard, WasmEdge’s Rust API can work with AI models in Tensorflow, PyTorch, OpenVINO, and other AI frameworks.</p>
<p>For AI inference applications with full Tensorflow Lite dependencies included, the WasmEdge footprint is less than 115MB. That compares to over 400MB for the standard Tensorflow Linux image.</p>
<p>Run the following two CLI commands to create and then deploy a <a target="_blank" href="http://fly.io">fly.io</a> app from our slim Docker image for WasmEdge + Tensorflow.</p>
<pre><code class="lang-bash">$ flyctl launch --image juntaoyuan/flyio-classify
$ flyctl deploy
</code></pre>
<p>That’s it! You can use the curl command to test whether the deployed web service actually works. It returns the image classification result with a confidence level.</p>
<pre><code class="lang-bash">$ curl https://silent-glade-6853.fly.dev/classify -X POST --data-binary <span class="hljs-string">"@grace_hopper.jpg"</span>
military uniform is detected with 206/255 confidence
</code></pre>
<p>The Dockerfile for the <code>juntaoyuan/flyio-classify</code> Docker image contains the complete package of the WasmEdge runtime, the entire Tensorflow libraries and their dependencies, and the custom web application <code>wasmedge_hyper_server_tflite.wasm</code>.</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> wasmedge/slim-tf:<span class="hljs-number">0.11</span>.<span class="hljs-number">0</span>
<span class="hljs-keyword">ADD</span><span class="bash"> wasmedge_hyper_server_tflite.wasm /</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"wasmedge-tensorflow-lite"</span>, <span class="hljs-string">"--dir"</span>, <span class="hljs-string">".:/"</span>, <span class="hljs-string">"/wasmedge_hyper_server_tflite.wasm"</span>]</span>
</code></pre>
<p>The Rust source code project to build the <code>wasmedge_hyper_server_tflite.wasm</code> application <a target="_blank" href="https://github.com/WasmEdge/wasmedge_hyper_demo/tree/main/server-tflite">is available on GitHub</a>. The tokio-based async HTTP server is in the async <code>main()</code> function as in the previous example.</p>
<p>The <code>classify()</code> function processes the image data in the request, turns the image into a tensor, runs the Tensorflow model, and then turns the return values (in a tensor) into text labels and probabilities for the possible classifications.</p>
<pre><code class="lang-rust"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">classify</span></span>(req: Request&lt;Body&gt;) -&gt; <span class="hljs-built_in">Result</span>&lt;Response&lt;Body&gt;, hyper::Error&gt; {
    <span class="hljs-keyword">let</span> model_data: &amp;[<span class="hljs-built_in">u8</span>] = include_bytes!(<span class="hljs-string">"models/mobilenet_v1_1.0_224/mobilenet_v1_1.0_224_quant.tflite"</span>);
    <span class="hljs-keyword">let</span> labels = <span class="hljs-built_in">include_str!</span>(<span class="hljs-string">"models/mobilenet_v1_1.0_224/labels_mobilenet_quant_v1_224.txt"</span>);
    <span class="hljs-keyword">match</span> (req.method(), req.uri().path()) {

        (&amp;Method::POST, <span class="hljs-string">"/classify"</span>) =&gt; {
            <span class="hljs-keyword">let</span> buf = hyper::body::to_bytes(req.into_body()).<span class="hljs-keyword">await</span>?;
            <span class="hljs-keyword">let</span> flat_img = wasmedge_tensorflow_interface::load_jpg_image_to_rgb8(&amp;buf, <span class="hljs-number">224</span>, <span class="hljs-number">224</span>);

            <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> session = wasmedge_tensorflow_interface::Session::new(&amp;model_data, wasmedge_tensorflow_interface::ModelType::TensorFlowLite);
            session.add_input(<span class="hljs-string">"input"</span>, &amp;flat_img, &amp;[<span class="hljs-number">1</span>, <span class="hljs-number">224</span>, <span class="hljs-number">224</span>, <span class="hljs-number">3</span>])
                .run();
            <span class="hljs-keyword">let</span> res_vec: <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">u8</span>&gt; = session.get_output(<span class="hljs-string">"MobilenetV1/Predictions/Reshape_1"</span>);
            ... ...

            <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> label_lines = labels.lines();
            <span class="hljs-keyword">for</span> _i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..max_index {
              label_lines.next();
            }
            <span class="hljs-keyword">let</span> class_name = label_lines.next().unwrap().to_string();

            <span class="hljs-literal">Ok</span>(Response::new(Body::from(<span class="hljs-built_in">format!</span>(<span class="hljs-string">"{} is detected with {}/255 confidence"</span>, class_name, max_value))))
        }

        <span class="hljs-comment">// Return the 404 Not Found for other routes.</span>
        _ =&gt; {
            <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            <span class="hljs-literal">Ok</span>(not_found)
        }
    }
}
</code></pre>
<p>In the last section of this article, we will discuss how to add more functionalities, such as database clients and web services clients, to the Rust microservice.</p>
<h2 id="heading-a-simple-microservice-in-nodejs">A Simple Microservice in Node.js</h2>
<p>While Rust-based microservices are light and fast, not everyone is a Rust developer (yet).</p>
<p>If you are more comfortable in JavaScript, you can still take advantage of WasmEdge’s security, performance, small footprint, and portability in the edge cloud. Specifically, you can use Node.js APIs to create microservices for WasmEdge!</p>
<p>For Node.js applications, the WasmEdge footprint is less than 15MB. That compares to over 150MB for the standard Node.js Linux image.</p>
<p>Run the following two CLI commands to create and then deploy a <a target="_blank" href="http://fly.io">fly.io</a> app from our slim Docker image for WasmEdge + Node.js.</p>
<pre><code class="lang-rust">$ flyctl launch --image juntaoyuan/flyio-nodejs-echo
$ flyctl deploy
</code></pre>
<p>That’s it! You can use the curl command to test whether the deployed web service actually works. It echoes back whatever data you post to it.</p>
<pre><code class="lang-bash">$ curl https://solitary-snowflake-1159.fly.dev -d <span class="hljs-string">"Hello WasmEdge for Node.js on fly.io!"</span>
Hello WasmEdge <span class="hljs-keyword">for</span> Node.js on fly.io!
</code></pre>
<p>The Dockerfile for the <code>juntaoyuan/flyio-nodejs-echo</code> Docker image contains the complete package of the WasmEdge runtime, the QuickJS runtime <code>wasmedge_quickjs.wasm</code>, Node.js <a target="_blank" href="https://wasmedge.org/book/en/dev/js/nodejs.html#the-javascript-modules">modules</a>, and the web service application <code>node_echo.js</code>.</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> wasmedge/slim-runtime:<span class="hljs-number">0.11</span>.<span class="hljs-number">0</span>
<span class="hljs-keyword">ADD</span><span class="bash"> wasmedge_quickjs.wasm /</span>
<span class="hljs-keyword">ADD</span><span class="bash"> node_echo.js /</span>
<span class="hljs-keyword">ADD</span><span class="bash"> modules /modules</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"wasmedge"</span>, <span class="hljs-string">"--dir"</span>, <span class="hljs-string">".:/"</span>, <span class="hljs-string">"/wasmedge_quickjs.wasm"</span>, <span class="hljs-string">"node_echo.js"</span>]</span>
</code></pre>
<p>The complete JavaScript source code for the <code>node_echo.js</code> application is as follows. As you can clearly see, it uses just standard Node.js APIs to create an asynchronous HTTP server that echoes back the HTTP request body.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createServer, request, fetch } <span class="hljs-keyword">from</span> <span class="hljs-string">'http'</span>;

createServer(<span class="hljs-function">(<span class="hljs-params">req, resp</span>) =&gt;</span> {
  req.on(<span class="hljs-string">'data'</span>, <span class="hljs-function">(<span class="hljs-params">body</span>) =&gt;</span> {
    resp.end(body)
  })
}).listen(<span class="hljs-number">8080</span>, <span class="hljs-function">() =&gt;</span> {
  print(<span class="hljs-string">'listen 8080 ...\n'</span>);
})
</code></pre>
<p>WasmEdge’s QuickJS engine provides not only Node.js support, but also Tensorflow inference support. We wrapped the Rust Tensorflow and WASI-NN SDKs into JavaScript APIs so that JavaScript developers could <a target="_blank" href="https://wasmedge.org/book/en/dev/js/tensorflow.html">easily create AI inference applications</a>.</p>
<h2 id="heading-stateful-microservices-on-the-edge">Stateful Microservices on the Edge</h2>
<p>With WasmEdge, it is also possible to create stateful microservices backed by databases. <a target="_blank" href="https://github.com/WasmEdge/wasmedge-db-examples">This GitHub repo</a> contains examples of tokio-based non-blocking database clients in WasmEdge applications.</p>
<ul>
<li><p>The <a target="_blank" href="https://github.com/WasmEdge/wasmedge-db-examples/tree/main/mysql">MySQL client</a> allows WasmEdge applications to access most cloud databases.</p>
</li>
<li><p>The <a target="_blank" href="https://github.com/essa-project/anna-rs">anna-rs project</a> is an edge-native KV store with adjustable sync and consistency levels on edge nodes. WasmEdge applications <a target="_blank" href="https://github.com/WasmEdge/wasmedge-db-examples/tree/main/anna">can use anna-rs</a> as an edge cache or database.</p>
</li>
</ul>
<p>You can now build a wide variety of web services on the edge cloud using WasmEdge SDKs and runtimes. Cannot wait to see your creations!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Serverless Meme-as-a-Service ]]>
                </title>
                <description>
                    <![CDATA[ The “meme economy” is apparently the next big thing. It is a natural extension of the Internet’s “attention economy”. Among many others, even Elon Musk is doing it. By some estimate, the meme economy is already worth $250 million USD. The meme econo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-serverless-meme-as-a-service/</link>
                <guid isPermaLink="false">66d46046d7a4e35e38434999</guid>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Thu, 25 Feb 2021 15:54:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/02/meme1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The “meme economy” is apparently the next big thing. It is a natural extension of the Internet’s “attention economy”. Among <a target="_blank" href="https://www.bloomberg.com/press-releases/2021-02-23/sino-global-shipping-partners-up-with-cybermiles-blockchain-to-explore-non-fungible-token-business">many others</a>, even <a target="_blank" href="https://www.axios.com/meme-economy-tesla-elon-musk-c1e9c225-d8e2-4953-a591-0a29dacf2d4a.html">Elon Musk is doing it</a>. By some estimate, the meme economy is already worth <a target="_blank" href="https://news.bitcoin.com/blockchain-backed-nft-market-value-grew-299-in-2020/">$250 million USD</a>.</p>
<blockquote>
<p>The meme economy is where FOMO meets YOLO. — Felix Salmon from AXIOS</p>
</blockquote>
<p>However, it takes time to create a meme. How about a web app that allows anyone to customize a meme and generate a new one? <a target="_blank" href="https://sls-website-ap-hongkong-hmtn9c-1302315972.cos-website.ap-hongkong.myqcloud.com/">That is a meme-as-a-service (MaaS)!</a></p>
<h2 id="heading-why-serverless">Why Serverless?</h2>
<p>As a developer, it is probably not difficult to create a web application that adds text captions to images. However, a meme-as-a-service has some additional requirements.</p>
<ul>
<li><p>The imaging processing task is often computationally intensive and requires high performance.</p>
</li>
<li><p>The meme service can see very little use or it could explode in popularity. In other words, it needs to be scalable and the developer only pays for actual use.</p>
</li>
</ul>
<p>There are solutions to the above issues. First, we will use a modern high-performance programming language to write the image and text manipulation function. We'll use Rust for this purpose, which delivers native performance but with memory safety.</p>
<p>Next, we can best address the scalability requirement with a serverless function in a public cloud. A serverless function is free when it is not used and can quickly scale to millions of users.</p>
<p>While it is possible to run a native program compiled from Rust as a serverless function, a better way is to run the Rust program in a WebAssembly VM as a serverless function.</p>
<p>The WebAssembly VM acts as a compatibility layer and the security sandbox between the native application and the serverless host environment. It allows the Rust program to be more portable as the WebAssembly VM is pre-configured to run in a variety of operating systems and container images required by public cloud serverless runtimes.</p>
<p>In addition, WebAssembly makes it easy for Rust programs to securely access software libraries written in C/C++. An example is to <a target="_blank" href="https://www.secondstate.io/articles/wasi-tensorflow/">access Tensorflow libraries in legacy operating systems from Rust</a>.</p>
<h2 id="heading-quick-start">Quick start</h2>
<p>In this tutorial, we will use <a target="_blank" href="https://github.com/second-state/tencent-meme-scf">a template project on GitHub</a> to deploy our Rust meme-as-a-service on Tencent Cloud. The template is based on the open source Serverless Framework.</p>
<p>The Rust program compiles to and runs on the Second State VM (SSVM), which is a WebAssembly VM optimized to run in cloud-based host environments.</p>
<blockquote>
<p>While we use Tencent Cloud in this example, the Serverless Framework is agnostic to all leading public clouds. You can easily deploy to AWS or Azure with minor changes.</p>
</blockquote>
<p>First, you will need to <a target="_blank" href="https://www.serverless.com/framework/docs/getting-started/">install the Serverless Framework</a> and create a free account on <a target="_blank" href="https://cloud.tencent.com/">Tencent Cloud</a>. Next, fork or clone the <a target="_blank" href="https://github.com/second-state/tencent-meme-scf">template GitHub repo</a> and then cd into its directory.</p>
<pre><code class="lang-bash">$ git <span class="hljs-built_in">clone</span> https://github.com/second-state/tencent-meme-scf
$ <span class="hljs-built_in">cd</span> tencent-meme-scf
</code></pre>
<p>You can now use the Serverless Framework to deploy the cloud function, an API gateway for the function service, and a static HTML page that uses the function service. It is configured to deploy to Tencent Cloud in the <code>.env</code> file.</p>
<p>Just follow the on screen instructions to log into Tencent Cloud and deploy.</p>
<pre><code class="lang-bash">$ sls deploy
... ...
  website:       https://sls-website-ap-hongkong-kfdilz-1302315972.cos-website.ap-hongkong.myqcloud.com
  vendorMessage: null

63s › tencent-meme-scf › <span class="hljs-string">"deploy"</span> ran <span class="hljs-keyword">for</span> 3 apps successfully.
</code></pre>
<p>Load the <code>website</code> URL in a browser to see your deployed <a target="_blank" href="https://sls-website-ap-hongkong-hmtn9c-1302315972.cos-website.ap-hongkong.myqcloud.com/">meme-as-a-service in action</a>! It allows you to customize the text, position, and size for each piece of caption / watermark on the meme picture.</p>
<h2 id="heading-how-the-application-works">How the application works</h2>
<p>The overall architecture of the application is a typical JAMStack app. The backend logic for image processing is deployed as a serverless function, and is available via an API.</p>
<p>The front end UI is a static HTML and JavaScript web page. The front end interacts with the backend API through JavaScript Ajax calls.</p>
<p>The backend serverless function for adding captions (or watermarks) to the meme background image is written in Rust in the <a target="_blank" href="https://github.com/second-state/tencent-meme-scf/blob/main/src/main.rs">main.rs</a> file. It first reads the font file for the watermark text and the background image file.</p>
<p>It then reads the input from the user application that specifies the text, position, and size of each watermark. The input is in the form of JSON text, and it is parsed into an array of Rust structs using the <code>serde_json</code> library.</p>
<p>The <code>_watermark()</code> function adds each watermark to the image. The function outputs the final image and base64 encodes it. The serverless runtime’s API gateway returns the base64 encoded image to the calling JavaScript to be displayed on the web page.</p>
<pre><code class="lang-rust"><span class="hljs-keyword">const</span> FONT_FILE : &amp;[<span class="hljs-built_in">u8</span>] = include_bytes!(<span class="hljs-string">"PingFang-Bold.ttf"</span>) <span class="hljs-keyword">as</span> &amp;[<span class="hljs-built_in">u8</span>];
<span class="hljs-keyword">const</span> TEMPLATE_BUF : &amp;[<span class="hljs-built_in">u8</span>] = include_bytes!(<span class="hljs-string">"bg.png"</span>) <span class="hljs-keyword">as</span> &amp;[<span class="hljs-built_in">u8</span>];

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
  <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> buffer = <span class="hljs-built_in">String</span>::new();
  io::stdin().read_to_string(&amp;<span class="hljs-keyword">mut</span> buffer).expect(<span class="hljs-string">"Error reading from STDIN"</span>);
  <span class="hljs-keyword">let</span> obj: FaasInput = serde_json::from_str(&amp;buffer).unwrap();

  <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> img = image::load_from_memory(TEMPLATE_BUF).unwrap();

  <span class="hljs-keyword">let</span> memes: <span class="hljs-built_in">Vec</span>&lt;Watermark&gt; = serde_json::from_str(&amp;(obj.body)).unwrap();
  <span class="hljs-keyword">for</span> m <span class="hljs-keyword">in</span> memes {
    _watermark(m, &amp;<span class="hljs-keyword">mut</span> img);
  }

  <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> buf = <span class="hljs-built_in">vec!</span>[];
  img.write_to(&amp;<span class="hljs-keyword">mut</span> buf, image::ImageOutputFormat::Png).unwrap();
  <span class="hljs-built_in">println!</span>(<span class="hljs-string">"{}"</span>, base64::encode_config(buf, base64::STANDARD));
}
</code></pre>
<p>The <code>_watermark()</code> function adds a piece of watermark text to the image. It utilizes the standard Rust image processing libraries (known as crates) to manipulate the meme image.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">_watermark</span></span>(w: Watermark, img: &amp;<span class="hljs-keyword">mut</span> image::DynamicImage) {
  <span class="hljs-keyword">let</span> font_size = w.font_size;

  <span class="hljs-keyword">let</span> font = <span class="hljs-built_in">Vec</span>::from(FONT_FILE);
  <span class="hljs-keyword">let</span> font = Font::try_from_vec(font).unwrap();

  <span class="hljs-keyword">let</span> scale = Scale {
    x: font_size,
    y: font_size,
  };
  drawing::draw_text_mut(img, image::Rgba([<span class="hljs-number">0u8</span>, <span class="hljs-number">0u8</span>, <span class="hljs-number">0u8</span>, <span class="hljs-number">255u8</span>]), w.left, w.top, scale, &amp;font, &amp;w.text);
}
</code></pre>
<p>The frontend JavaScript takes the user input text, position, and font size from the HTML form, submits the input data in JSON to the cloud function, and then displays the returned base64 image.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> memes = [];
memes[<span class="hljs-number">0</span>] = {};
memes[<span class="hljs-number">0</span>].text = $(<span class="hljs-string">'#top-says'</span>).val();
memes[<span class="hljs-number">0</span>].left = <span class="hljs-built_in">parseInt</span>($(<span class="hljs-string">'#top-left'</span>).val());
memes[<span class="hljs-number">0</span>].top = <span class="hljs-built_in">parseInt</span>($(<span class="hljs-string">'#top-top'</span>).val());
memes[<span class="hljs-number">0</span>].font_size = <span class="hljs-built_in">parseInt</span>($(<span class="hljs-string">'#top-font'</span>).val());
... ...

$.ajax({
  <span class="hljs-attr">url</span>: <span class="hljs-built_in">window</span>.env.API_URL,
  <span class="hljs-attr">type</span>: <span class="hljs-string">"post"</span>,
  <span class="hljs-attr">data</span> : <span class="hljs-built_in">JSON</span>.stringify(memes),
  <span class="hljs-attr">dataType</span>: <span class="hljs-string">"text"</span>,
  <span class="hljs-attr">success</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">data</span>) </span>{
    <span class="hljs-keyword">const</span> img_url = <span class="hljs-string">"data:image/png;base64,"</span> + data;
    $(<span class="hljs-string">'#wm_img'</span>).prop(<span class="hljs-string">'src'</span>, img_url);
  },
  <span class="hljs-attr">error</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">jqXHR, exception</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Error Status: "</span> + jqXHR.statusText);
  }
});
</code></pre>
<h2 id="heading-build-your-own-meme-as-a-service">Build your own meme-as-a-service</h2>
<p>With the source code template, you can create your own meme-as-a-service. You can change the meme background image, and change the UI for adding text watermarks.</p>
<p>To do that, first make sure that you have installed the <a target="_blank" href="https://www.rust-lang.org/tools/install">Rust</a> compiler and <a target="_blank" href="https://www.secondstate.io/articles/ssvmup/">ssvmup</a> build tools.</p>
<p>Make changes to the Rust code and the HTML document. Compile the Rust function to WebAssembly, and copy the result to the <code>scf/</code> folder.</p>
<pre><code class="lang-bash">$ ssvmup build --enable-aot
$ cp pkg/scf.so scf/
</code></pre>
<p>Run the serverless framework command to deploy the application.</p>
<pre><code class="lang-bash">$ sls deploy
... ...
  website:       https://sls-website-ap-hongkong-kfdilz-1302315972.cos-website.ap-hongkong.myqcloud.com
  vendorMessage: null

63s › tencent-meme-scf › <span class="hljs-string">"deploy"</span> ran <span class="hljs-keyword">for</span> 3 apps successfully.
</code></pre>
<h2 id="heading-whats-next">What’s next</h2>
<p>Now that you have created and published your own meme-as-a-service, congratulations!</p>
<p>There is much more you can do with the JAMStack application and serverless functions. For example, you can create serverless functions for Tensorflow inference to incorporate advanced image recognition and processing to your application.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Personal Dev Server on a $5 Raspberry Pi ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you'll learn how to build a personal dev server by installing Git, Node.js, Rust, and Docker on a Raspberry Pi. The cheapest option costs just $5. You can get a starter kit ($25) for free here. The Raspberry Pi is a very powerful com... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-personal-dev-server-on-a-5-dollar-raspberry-pi/</link>
                <guid isPermaLink="false">66d46042230dff0166905827</guid>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Raspberry Pi ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Fri, 17 Jul 2020 20:46:37 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/07/IMG_8632.JPG" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you'll learn how to build a personal dev server by installing Git, Node.js, Rust, and Docker on a Raspberry Pi. The cheapest option costs just $5. <a target="_blank" href="https://www.secondstate.io/articles/raspberry-pi-for-free-20200709/">You can get a starter kit ($25) for free here</a>.</p>
<p>The Raspberry Pi is a very powerful computer in a tiny package. The cheapest option, the <a target="_blank" href="https://www.raspberrypi.org/products/raspberry-pi-zero/">Raspberry Pi Zero</a>, is capable of running a fully featured Linux distribution and driving a high definition display. It is the size of two coins (US Quarters) and costs $5.</p>
<p>At $10, the <a target="_blank" href="https://www.raspberrypi.org/products/raspberry-pi-zero-w/">Raspberry Pi Zero W</a> comes with integrated WiFi and Bluetooth.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/img_8603.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The $10 Raspberry Pi Zero W has a powerful CPU, WiFi, Bluetooth, and all kinds of connectors</em></p>
<p>At the “high end”, you can purchase a <a target="_blank" href="https://www.raspberrypi.org/products/raspberry-pi-4-desktop-kit/">Raspberry Pi 4 desktop kit</a> for less than $100. It has a 4-core ARM CPU running at 1.5GHz, GPU, 2GB (up to 8 GB) of RAM, 16GB (up to 2TB) of storage on MicroSD cards, wifi and Ethernet connectors, USB ports, HDMI ports that can drive 4K displays, as well as a keyboard and mouse.</p>
<p>The Raspberry Pi is also more than a standard computer. It is fun and hackable. The Raspberry Pi exposes a row of GPIO (General Purpose Input Output) pins. You can attach simple sensors (eg. temperature, humidity, light) to those pins, and capture their data from your applications running on the Pi.</p>
<p>You could also attach LED lights and motors to those pins, and use your Pi application to drive those peripheral devices.</p>
<p>For more complex sensors or devices, such as camera modules, you can also connect to the Pi via USB or Wifi, and access them in software. The Pi is a great device for learning and hardware hacking. Because of this, it is widely used in educational settings.</p>
<p>However, fun and learning are not just for kids. With so much computing power and easy networking, the Raspberry Pi can easily become a personal application server for you.</p>
<p>For example, you can put a web application (for example, a collaborative note taking app, or just some documents / videos to share) on a Pi, bring it to a meeting, and make it accessible to everyone in the room. You do not even need the Internet. It is completely decentralized and censorship-resistant.</p>
<p>The personal server is especially useful for developers. You can have a separate environment to deploy and test your server-side applications without having to mess with your laptop. A personal dev server is like Docker on steroids. In this article, I will teach you how to set one up.</p>
<h2 id="heading-first-get-a-raspberry-pi">First, get a Raspberry Pi</h2>
<p>If this is your first Raspberry Pi, the easiest (and most expensive) way to set up is just to buy a <a target="_blank" href="https://www.raspberrypi.org/products/raspberry-pi-4-desktop-kit/">desktop kit for around $100</a>. It comes with everything you need for a computer except for the display.</p>
<p>If you are using the Pi as a personal dev server, you would NOT need a display after the initial setup. You can just SSH into it from your laptop once it is turned on!</p>
<p><a target="_blank" href="https://www.secondstate.io/articles/raspberry-pi-for-free-20200709/">Learn how</a> to get your Raspberry Pi starter kit for free when you participate in this <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">high performance web application learning exercise</a>.</p>
<p>Of course, if you have spare computer parts, such as MicroSD cards, USB power supply, a keyboard, and a mouse laying around, you could save money by purchasing only the boards. You could get a Raspberry Pi Zero board for $5 and a Raspberry Pi 4 board for $35.</p>
<p>But the thing missing from the board is a MicroSD card that acts as the “hard drive” for storing the operating system and data. You can purchase a 16GB MicroSD card for $10 online, a MicroSD card reader, and use the <a target="_blank" href="https://www.raspberrypi.org/downloads/">Raspberry Pi Imager</a> to load an operating system onto the MicroSD card from your laptop.</p>
<p>The two popular choices are Raspberry Pi OS and Ubuntu Linux. Both are Debian-based Linux distributions. Most starter kits pre-install the Raspberry Pi OS on their MicroSD cards (it is called NOOBS).</p>
<p>In the next two sections, I will talk you through both operating systems.</p>
<h2 id="heading-how-to-set-up-raspberry-pi-os">How to set up Raspberry Pi OS</h2>
<p>Once you put in the MicroSD card with NOOBS, and connect a display, a keyboard, and a mouse, you can turn on the power!</p>
<p>From there, just follow on screen instructions to install Raspberry Pi OS (previously known as the Raspbian OS). Then setup a password for the user pi, and setup the wifi connection.</p>
<p>After you are logged in, go to the Preferences → Raspberry Pi Configuration menu and enable SSH. That will allow you to log into the Pi from another computer.</p>
<p><strong>Note</strong>: in order to use the Pi as a “headless” server, you could request a static IP address from your router. In the future, you can just power on the Pi, and connect to it via SSH from your other computers or phones.</p>
<p>The Raspberry Pi OS is derived from the Debian Linux distribution. It comes with a full desktop UI environment with a modern web browser, a command line terminal, and learning programs such as IDEs for Python, Java, and Scratch.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/IMG_8672.JPG" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>My Raspberry Pi 4 with Raspberry Pi OS setup. Notice how small the actual computer is.</em></p>
<p>For our purposes, we are mostly interested in installing dev and server software through the command line terminal.</p>
<p>At this point, you could also find out the IP address of the Pi on your local network by running the following command. Then you can SSH into the Pi using that local IP address, username pi, and the password you gave pi during setup.</p>
<pre><code class="lang-javascript">$ hostname -I
<span class="hljs-number">192.168</span><span class="hljs-number">.2</span><span class="hljs-number">.108</span> <span class="hljs-number">172.17</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>
</code></pre>
<p>You can find a <a target="_blank" href="https://n8henrie.com/2019/08/list-of-default-packages-on-raspbian-buster-lite/">complete list of software packages installed on the Raspberry Pi OS here</a>. It is always a good idea to update and upgrade to the latest packages. Run the command below and be patient. It could take an hour.</p>
<pre><code class="lang-javascript">$ sudo apt update &amp;&amp; sudo apt upgrade
</code></pre>
<h2 id="heading-how-to-set-up-ubuntu-server-2004">How to set up Ubuntu Server 20.04</h2>
<p>The Raspberry Pi OS is primarily geared toward a desktop experience. For developers who just want to use the device as a server or IoT device, the Ubuntu Linux is a much better choice. It has the latest software packages and libraries, and could be far more efficient without the desktop windows, web browser, Java, games, and learning tools.</p>
<p>You can download <a target="_blank" href="https://ubuntu.com/download/raspberry-pi">Ubuntu Server images for Raspberry Pi</a> from the web, and load it on a MicroSD card. But perhaps a much easier way is just to use the <a target="_blank" href="https://www.raspberrypi.org/downloads/">Raspberry Pi Imager</a>, select Ubuntu Server 20.04 TLS from the menu, and write into an empty MicroSD card.</p>
<p>Once the MicroSD card is prepared, you should <a target="_blank" href="https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#3-wifi-or-ethernet">follow these instructions</a> to put in your WiFi network name and password. This allows the Raspberry Pi device to connect to the network as soon as it boots.</p>
<p>Basically, you can just put the MicroSD card into the Raspberry Pi, connect USB power, then wait for it to come online. You can find the <code>raspberrypi</code> device IP from your WiFi router, and then SSH into from any computer on your network.</p>
<p>The initial username and password are <code>ubuntu / ubuntu</code>. There is no need to even connect a monitor or keyboard. That’s it for a completely headless setup!</p>
<p><strong>Note</strong>: if, for some reason, your Raspberry Pi cannot connect to WiFi at startup, you can hook up an HDMI display and a USB keyboard to it. Then <a target="_blank" href="https://linuxconfig.org/ubuntu-20-04-connect-to-wifi-from-command-line">follow these instructions</a> to debug and set up WiFi on the running system.</p>
<p>Next, let's install the developer tool stack on the Pi.</p>
<h2 id="heading-install-git">Install Git</h2>
<p>I always install Git on all my development environments because a lot of software can be directly retrieved from Git repositories. It saves me the trouble of downloading and copying.</p>
<p>Git also allows me to save and backup my own work in private repositories. For a small computer like Raspberry Pi, I would recommend that you save work in Git in case you lose the device or MicroSD card.</p>
<p>The following command installs Git:</p>
<pre><code class="lang-javascript">$ sudo apt install git
</code></pre>
<h2 id="heading-install-nodejs">Install Node.js</h2>
<p>To turn the Raspberry Pi into a personal dev server for web applications, you need to install a modern web application runtime.</p>
<p>For most developers today, the best starting point is Node.js, which allows you to write server-side applications in JavaScript. The following two commands install Node.js on your Pi.</p>
<pre><code class="lang-javascript">$ curl -sL https:<span class="hljs-comment">//deb.nodesource.com/setup_10.x | sudo bash -</span>
$ sudo apt install nodejs
</code></pre>
<p>You can verify the installation is done correctly by running the following two commands. Both node and npm are now available.</p>
<pre><code class="lang-javascript">$ node -v
v10<span class="hljs-number">.19</span><span class="hljs-number">.0</span>
$ npm -v
<span class="hljs-number">5.8</span><span class="hljs-number">.0</span>
</code></pre>
<p>From here, you can use npm to install modules. For example, a commonly used npm module is the express framework for web applications.</p>
<pre><code class="lang-javascript">$ npm install express
</code></pre>
<p>Now, you can go through the <a target="_blank" href="https://expressjs.com/en/starter/hello-world.html">ExpressJS hello world example</a> to create a web server on your Pi, and use web browsers from any computer on your network to access the application!</p>
<h2 id="heading-install-rust">Install Rust</h2>
<p>Rust is a fast growing programming language for writing both systems and web applications. It is close to the hardware, high performance, and memory safe. That makes Rust a great language for writing applications on resource constrained devices like the Raspberry Pi.</p>
<p>Also, Rust is the most beloved programming language by StackOverflow users for the past 5 years in a row. It is well worth your time to learn it!</p>
<p>An important use case of Rust is to compile <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">Rust functions into WebAssembly and run them inside Node.js</a> applications to achieve <a target="_blank" href="https://www.secondstate.io/articles/why-webassembly-server/">performance, safety, and code portability</a>. It is a great choice for running computationally intensive web applications on a small <a target="_blank" href="https://www.secondstate.io/articles/get-started-with-raspberry-pi-20200708/">Raspberry Pi device</a>. In fact, you could <a target="_blank" href="https://www.secondstate.io/articles/raspberry-pi-for-free-20200709/">get a free Raspberry Pi starter kit</a> if you learn how to do that.</p>
<p>Note: strictly speaking, you do not need to install Rust tools on the Pi. You typically only need to run Rust programs in the Pi. You can compile your Rust program on any computer and then copy the compiled binaries to the Pi.</p>
<p>But still, with the powerful CPU, you can compile Rust programs on the Raspberry Pi. So why not?</p>
<p>The following command installs the Rust compiler toolchain on the Pi.</p>
<pre><code class="lang-javascript">$ curl --proto <span class="hljs-string">'=https'</span> --tlsv1<span class="hljs-number">.2</span> -sSf https:<span class="hljs-comment">//sh.rustup.rs | sh</span>
</code></pre>
<p>Run the following command to set up the correct path without logging out and back in again.</p>
<pre><code class="lang-javascript">$ source $HOME/.cargo/env
</code></pre>
<p>The above command also installs the Rust package manager called cargo. Most Rust developers use cargo to build and share their work.</p>
<pre><code class="lang-javascript">$ cargo -V
cargo <span class="hljs-number">1.44</span><span class="hljs-number">.1</span> (<span class="hljs-number">88</span>ba85757 <span class="hljs-number">2020</span><span class="hljs-number">-06</span><span class="hljs-number">-11</span>)
</code></pre>
<p>Next, you can clone our <a target="_blank" href="https://github.com/second-state/wasm-learning/">Rust learning repository</a>, and learn from examples.</p>
<pre><code class="lang-javascript">$ git clone https:<span class="hljs-comment">//github.com/second-state/wasm-learning.git</span>
</code></pre>
<p>Here is the <a target="_blank" href="https://www.secondstate.io/articles/a-rusty-hello-world/">hello world example</a>. Have fun!</p>
<pre><code class="lang-javascript">$ cd wasm-learning/rust/hello
$ cargo build
   Compiling hello v0<span class="hljs-number">.1</span><span class="hljs-number">.0</span> (<span class="hljs-regexp">/home/</span>pi/Dev/wasm-learning/rust/hello)
    Finished dev [unoptimized + debuginfo] target(s) <span class="hljs-keyword">in</span> <span class="hljs-number">4.35</span>s
$ target/debug/hello
Hello, world!
</code></pre>
<p>Check out the <a target="_blank" href="https://www.rust-lang.org/learn">official Rust web site</a> and the <a target="_blank" href="https://rust-by-example-ext.com/">Rust by Example</a> books for more learning resources.</p>
<h2 id="heading-learn-docker">Learn Docker</h2>
<p>We have seen that the Raspberry Pi OS and Ubuntu Server are both very capable Linux distributions with lots of software packages.</p>
<p>But what if I want to test applications on other OSes? Do I need to wipe clean and reinstall a different OS on the MicroSD card? The answer is no. You can just use Docker! The following two commands install docker on the Raspberry Pi:</p>
<pre><code class="lang-javascript">$ curl -fsSL https:<span class="hljs-comment">//get.docker.com -o get-docker.sh</span>
$ sudo sh get-docker.sh
</code></pre>
<p>Run the following command so that you can use Docker as the pi user:</p>
<pre><code class="lang-javascript">$ sudo usermod -aG docker pi
</code></pre>
<p>The Docker info command shows that Docker is now installed on an ARM system with Raspberry Pi OS.</p>
<pre><code class="lang-javascript">$ docker info
... ...
 Kernel Version: <span class="hljs-number">4.19</span><span class="hljs-number">.118</span>-v7l+
 Operating System: Raspbian GNU/Linux <span class="hljs-number">10</span> (buster)
 <span class="hljs-attr">OSType</span>: linux
 <span class="hljs-attr">Architecture</span>: armv7l
 <span class="hljs-attr">CPUs</span>: <span class="hljs-number">4</span>
 Total Memory: <span class="hljs-number">3.814</span>GiB
 <span class="hljs-attr">Name</span>: raspberrypi
 <span class="hljs-attr">ID</span>: XERI:ZVVZ:XQVA:HXSH:KRPI:<span class="hljs-number">6</span>GL2:<span class="hljs-number">5</span>QRE:E7GZ:Z72Q:<span class="hljs-number">6</span>SGF:CEI6:GKTC
 Docker Root Dir: <span class="hljs-regexp">/var/</span>lib/docker
... ...
</code></pre>
<p>Next, you can pull a Docker image for the latest Ubuntu distribution, run it, and log into Ubuntu as a command line user.</p>
<pre><code class="lang-javascript">$ docker pull ubuntu
... ...
$ docker run -it ubuntu bash
root# ... enter commands ...
</code></pre>
<h2 id="heading-whats-next">What’s next?</h2>
<p>In this article, we have touched on the basics and learned how to turn your Raspberry Pi 4 device into a personal dev server for software developers.</p>
<p>There is much to learn about Git, Node.js, Rust, WebAssembly and Docker. There are also many other developer stacks you can install on the Raspberry Pi.</p>
<p><a target="_blank" href="https://www.secondstate.io/articles/raspberry-pi-for-free-20200709/">Grab your free Raspberry Pi kit</a> and let us know what you did with it!</p>
<p><a target="_blank" href="https://webassemblytoday.substack.com/">Subscribe to our newsletter</a> and stay in touch.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ GitHub Codespaces – How to Code Right in Your Browser with Your Own Cloud Dev Environment ]]>
                </title>
                <description>
                    <![CDATA[ GitHub Codespaces enable you to experiment with complex software development stacks right from the web browser. No software to install or configure. No stress. No mess. A gif showing the setup process of a GitHub Codespace In the recent GitHub Satel... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-programming-in-your-browser-the-right-way/</link>
                <guid isPermaLink="false">66d4604a264384a65d5a95ac</guid>
                
                    <category>
                        <![CDATA[ codespaces ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WebAssembly ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Tue, 09 Jun 2020 21:34:29 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9a61740569d1a4ca2547.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>GitHub Codespaces enable you to experiment with complex software development stacks right from the web browser. No software to install or configure. No stress. No mess.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/SSVM-edited-without-music-1-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>A gif showing the setup process of a GitHub Codespace</em></p>
<p>In the recent GitHub Satellite online conference, one of the most exciting product announcements was GitHub Codespaces. The idea is to have a code button on every repository.</p>
<p>When you click on it, it launches a fully featured VSCode IDE with all the necessarily software dependencies, including operating system level libraries, to build and run the project. This VSCode IDE runs entirely in your browser, and will not install any software or change any configuration to mess up your computer.</p>
<p>Sounds too good to be true? Well, watch the Github Satellite keynote segment about Codespaces yourself!</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/fQbH3meWNQ8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>A key benefit of Github Codespaces is how quickly you can on-board new developers to a project. A new developer can get set up in minutes, instead of days, and immediately start contributing to the project. It is a great learning tool for new languages, frameworks, and software tools.</p>
<p>Under the hood, it starts a Docker container on a remote server, installs the entire software stack required by the project, and runs tasks like compiling and debugging in the remote Docker.</p>
<p>The web browser acts as a front end UI for the Docker instance. This approach requires no software install on the developer’s machine. But the trade-off is that all software installation from the operation system all the way to the final application happens on the server.</p>
<p>GitHub must start a fresh server for each Codespaces instance. That requires a lot of data center resources. In fact, the <a target="_blank" href="https://github.com/features/codespaces/">GitHub Codespaces web page</a> has a waiting list as of today (June 2020).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/codespaces-beta.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Personally, I cannot wait for GitHub Codespaces to become available. But a time machine does exist. You can experience all the features in GitHub Codespaces today, for free.</p>
<h2 id="heading-vs-codespaces">VS Codespaces</h2>
<p>The software behind GitHub Codespaces is actually based on a Microsoft VSCode product called <a target="_blank" href="https://online.visualstudio.com/">VS Codespaces</a>. VS Codespaces is available today to all Microsoft Azure users. And yes, it allows you to open GitHub repositories in VSCode IDE directly from a browser window.</p>
<p>In this tutorial, I will show you how to use Codespaces in your own development work today.</p>
<p>To make Codespaces available in your GitHub repositories, you just need to add the following HTML button anywhere on your web pages.</p>
<p>When an Azure user clicks on the button, it asks the user to log into VS Codespaces and walks the user through opening the repository in the online IDE. You can see how it works in the examples in the next section.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://online.visualstudio.com/environments/new?name=My%20Project&amp;repo=username/reponame"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://img.shields.io/endpoint?style=social&amp;url=https%3A%2F%2Faka.ms%2Fvso-badge"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<blockquote>
<p>VS Codespaces runs entirely in your browser and costs around $1 per work day. It is cheaper than a cup of coffee in the office.</p>
</blockquote>
<h2 id="heading-examples">Examples</h2>
<p>Now, let's look into several examples of how you might learn new programming skills using VS Codespaces.</p>
<p>Rust is one of the fastest growing programming languages today. It is voted as the most beloved programming language by Stackoverflow users four years in a row.</p>
<p>But to experiment with Rust requires a complex toolchain of compiler, linker, package manager, tool manager and so on.</p>
<p>VS Codespaces provides an easy way to <a target="_blank" href="https://www.secondstate.io/articles/how-to-learn-rust-without-installing-any-software/">learn Rust</a>. Just click on the VS Codespaces button in <a target="_blank" href="https://github.com/second-state/learn-rust-with-github-actions">this repository</a> and you now have a working Rust project to experiment with!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/learn-rust-20-seconds.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://github.com/second-state/learn-rust-with-github-actions"><em>https://github.com/second-state/learn-rust-with-github-actions</em></a></p>
<p>As a system language, Rust is well positioned to build high performance server side applications. The most promising stack is to compile and run Rust functions in a WebAssembly container, and then access those high performance functions from an existing web application framework, such as Node.js.</p>
<p>However, as you can already see, this “best practice” setup requires a complex stack of software.</p>
<p>Clicking on the VS Codespaces button in <a target="_blank" href="https://github.com/second-state/ssvm-nodejs-starter">this repository</a> gives you a fully functional Node.js project that uses <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">Rust functions in WebAssembly</a> as modules. You can immediately start to modify the Rust and JavaScript code and run the Node.js application from inside the web browser IDE.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/SSVM-edited-without-music.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://github.com/second-state/ssvm-nodejs-starter"><em>https://github.com/second-state/ssvm-nodejs-starter</em></a></p>
<p><a target="_blank" href="https://www.secondstate.io/articles/why-webassembly-server/">Server-side Rust and WebAssembly</a> sound cool. But do we actually have a more complete example that demonstrate the power and performance of Rust beyond a simple hello world?</p>
<p><a target="_blank" href="https://github.com/second-state/rust-wasm-ai-demo">This repository</a> is such an example. Open it in VS Codespaces and you will have a project for a <a target="_blank" href="https://www.secondstate.io/articles/artificial-intelligence/">Rust + JavaScript app that utilizes Tensorflow to perform image recognition</a>. Since the app runs inside Node.js, it provides a template for AI-as-a-Service web applications.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/68747470733a2f2f626c6f672e7365636f6e6473746174652e696f2f696d616765732f414961617325323033307365636f6e64732e676966.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://github.com/second-state/rust-wasm-ai-demo"><em>https://github.com/second-state/rust-wasm-ai-demo</em></a></p>
<p>What if you want to stay on the bleeding edge and use Rust-based web runtime Deno instead of the C-based Node.js? Well, there is a VS Codespaces <a target="_blank" href="https://github.com/anthonychu/azure-functions-deno-worker">template for running Deno as an Azure Function</a> too!</p>
<h2 id="heading-how-it-works">How it works</h2>
<p>If you look closely, each VS Codespaces-enabled repository has a <code>.devcontainer</code> folder. Inside that folder, the <code>Dockerfile</code> specifies how to build the Docker container for the development environment.</p>
<p>For example, the Node.js Docker container is based on Ubuntu Linux with Node.js and selected NPM packages pre-installed. <a target="_blank" href="https://github.com/second-state/ssvm-nodejs-starter/tree/master/.devcontainer">Check out an example here</a>.</p>
<p>The <code>devcontainer.json</code> file specifies the configuration for the VSCode IDE on the remote Docker. For example, it configures the VSCode extensions to install, the terminal and debugger commands to use, and the host ports to forward to for testing and debugging.</p>
<p>Microsoft provides <a target="_blank" href="https://github.com/microsoft/vscode-dev-containers">quite a few <code>.devcontainer</code> templates</a> for you to modify and use. They cover most of the common software development stacks today.</p>
<p>You could further customize the user’s VSCode experience by providing launch and tasks definitions in the <code>.vscode</code> folder. <a target="_blank" href="https://github.com/second-state/ssvm-nodejs-starter/tree/master/.vscode">Check them out</a>!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With VS Codespaces, and GitHub Codespaces when it launches, the barriers and friction for software development are further reduced. You can get started with complex software stacks without leaving your web browser. <a target="_blank" href="https://www.secondstate.io/articles/getting-started-rust-nodejs-vscode/">Try it today</a>!</p>
<p>Finally, watch the full length GitHub Satellite presentation on GitHub Codespaces.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/dy2eYaNxaQc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p><a target="_blank" href="https://webassemblytoday.substack.com/">Subscribe to my newsletter</a> and stay in touch.</p>
<div class="embed-wrapper"><iframe src="https://webassemblytoday.substack.com/embed" width="480" height="320" style="border:1px solid #EEE;background:white" title="Embedded content" loading="lazy"></iframe></div> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Top 8 Things I Learned From 4000 Rust Developers ]]>
                </title>
                <description>
                    <![CDATA[ Do you know that most Rust programmers are working on web applications? ? Rust is challenging, but also rewarding and great fun! Learn Rust by example, or ?open this GitHub repo to get started in VSCode. Rust is one of the hottest ? programming langu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/8-things-i-learned-from-4000-rust-developers/</link>
                <guid isPermaLink="false">66d460404bc8f441cb6df811</guid>
                
                    <category>
                        <![CDATA[ codespaces ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programming languages ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WebAssembly ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Sun, 24 May 2020 17:57:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/learn-rust-20-seconds-1.gif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Do you know that most Rust programmers are working on web applications? ? Rust is challenging, but also rewarding and great fun! Learn <a target="_blank" href="https://rust-by-example-ext.com/">Rust by example</a>, or ?open <a target="_blank" href="https://github.com/second-state/learn-rust-with-github-actions">this GitHub repo</a> to get started in VSCode.</p>
<p>Rust is one of the hottest ? programming languages today. It is StackOverflow's <a target="_blank" href="https://stackoverflow.blog/2020/01/20/what-is-rust-and-why-is-it-so-popular/">most beloved programming language</a> for the past 4 years. Yet, it still has a reputation as the programming language for alpha geeks.</p>
<p>By <a target="_blank" href="https://s3-eu-west-1.amazonaws.com/vm-blog/uploads/2020/04/DE18-SoN-Digital-.pdf">some estimate</a>, there are 600,000 Rust developers world-wide, which is a significant number. But it's still dwarfed when compared with tens of millions of JavaScript, Java, and Python developers.</p>
<p>Who are those Rust developers? What are they using Rust for? Why do they love Rust so much? And most important, how do you join their ranks and see for yourself why Rust is so beloved? Don't get left behind.</p>
<p>In order to answer those questions, the Rust community has conducted annual developer surveys from rust-lang.org since 2016. The site recently released its <a target="_blank" href="https://blog.rust-lang.org/2020/04/17/Rust-survey-2019.html">2019 survey results</a> based on responses from nearly 4000 Rust developers. Here are the top 8 things I learned from the survey.</p>
<h2 id="heading-rust-is-for-professional-programmers">??‍? Rust is for professional programmers</h2>
<p>The Rust programming language is not designed to be “<a target="_blank" href="https://www.secondstate.io/articles/a-rusty-hello-world/">easy to get started</a>”. Rather, it is designed to be powerful and safe at the same time. It aims to be the developer productivity language for professional programmers. It is challenging, fun, and rewarding. That shows in the survey.</p>
<p>Very few respondents call themselves as Rust experts. Most people rate their Rust expertise as 7/10 or below, despite the fact that over 68% of them write Rust code on a weekly basis. It is clearly a language that takes time to master and excel.</p>
<blockquote>
<p>About 37% of Rust users felt productive in Rust in less than a month of use - this is not too different from the percentage last year (40%). Over 70% felt productive in their first year. Unfortunately, like last year, there is still a struggle among users - 21% indicated they did not yet feel productive.</p>
</blockquote>
<p>At the same time, when asked why not using Rust on some projects, the learning curve is cited as the #2 most common reason. The #1 reason, of course, is the company’s decision whether to use a particular programming language in a project.</p>
<h2 id="heading-documentation-is-critical-for-adoption">? Documentation is critical for adoption</h2>
<p>How do developers overcome Rust's learning curve and fall in love with it? Well, not unexpectedly, most developers cited “better documentation” as the driver for adoption.</p>
<p>But true to “professional programmers”, the most sought after Rust documentation is intermediate-level content that helps developers improve their Rust skills and productivity.</p>
<p>While the survey is biased toward developers who already knew the basics of Rust, it seems that there is a thirst for knowledge and self-improvement in this crowd.</p>
<h2 id="heading-developers-do-not-want-tomes-of-text">? Developers do not want tomes of text</h2>
<p>Traditional software documentation typically consists of entire books and websites. New generations of developers want more and better documentation. As a “new” language, Rust is already leading the innovation when it comes to programming language documentation.</p>
<p>For example, the Rust compiler is a self-documenting tool. One of the most unique and beloved features of Rust is its aggressive compiler that helps you ensure correctness and safety before the program even runs. As a result, Rust developers can write highly performant yet safe programs.</p>
<p>When you encounter a compiling error in Rust, the compiler gives you an immediate explanation of the error, and suggestions on how to fix the error based on the context of your program.</p>
<p><a target="_blank" href="https://github.com/second-state/learn-rust-with-github-actions">This starter project</a> in GitHub gets you started with the Rust compiler and the Cargo system without having to install any software toolchain. You can use the VSCode online IDE directly with this project.</p>
<p>Rust documentation web sites like <a target="_blank" href="http://docs.rs">docs.rs</a> and <a target="_blank" href="https://doc.rust-lang.org/rust-by-example/">Rust by Example</a> (and its <a target="_blank" href="https://rust-by-example-ext.com/">Extended Edition</a>) use the <a target="_blank" href="https://play.rust-lang.org/">Rust Playground</a> to run Rust example code directly from the browser. Those interactive books are much better than simple text.</p>
<p>However, as the survey finds out, developers want more. Developers are thirsty for more video content, for example. We can look forward to more coding videos and live broadcasts from the community soon.</p>
<h2 id="heading-most-people-use-rust-for-web-apps-srsly">?️ Most people use Rust for web apps, srsly!</h2>
<p>As a system-level language intended to replace C and C++, most people assume that Rust would be used in infrastructure programming, such as operating systems, native libraries, and runtime platforms.</p>
<p>Yet, the survey clearly shows that by a large margin, most Rust developers today are working on web app backends. No wonder crates like <a target="_blank" href="https://docs.rs/hyper/0.13.5/hyper/">hyper</a>, <a target="_blank" href="https://github.com/actix/actix-web">actix-web</a>, and <a target="_blank" href="https://rocket.rs/">Rocket</a> are among the most popular with Rust developers.</p>
<p>To be sure, most software developers are working on web applications. It is not surprising that, as Rust gains mainstream adoption, Rust projects will mirror the bigger software industry.</p>
<p>However, that does present opportunities for projects and tools that integrates Rust into popular web application runtimes. For example, the <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">Rust + JavaScript hybrid application</a> approach is gaining momentum.</p>
<h2 id="heading-blockchain-is-a-rusty-hotbed">? Blockchain is a Rusty hotbed</h2>
<p>When it comes to infrastructure software, Rust really shines as a programming language for blockchain systems.</p>
<p>For all software related industry sectors, the survey shows that blockchain only ranks the 35th for all software developers, but 11th for Rust developers. That is in no small part due to aggressive Rust adoption by large blockchain projects such as <a target="_blank" href="https://www.parity.io/">Polkadot / Substrate</a>, <a target="_blank" href="https://www.oasislabs.com/">Oasis</a>, <a target="_blank" href="https://solana.com/">Solana</a>, and <a target="_blank" href="https://www.secondstate.io/">Second State</a> etc.</p>
<p>In many ways, blockchains are perfect fit for Rust. Blockchains represent the community effort to re-build the internet infrastructure in a decentralized manner. They require high performance software that is also very safe. If you are interested in a career as a blockchain engineer, Rust is a must-have skill today.</p>
<h2 id="heading-rust-webassembly">Rust ❤️ WebAssembly</h2>
<p>The survey reveals that WebAssembly is a popular runtime environment for Rust programs. Rust and WebAssembly were both invented at Mozilla.</p>
<p>Rust is focused on performance and memory safety, while WebAssembly is focused on performance and runtime safety. As a runtime container, WebAssembly also makes Rust programs cross-platform and more manageable. There are indeed a lot of synergy between the two technologies.</p>
<p>WebAssembly was originally invented as a client side virtual machine to run in-browser applications. But as Java and JavaScript before it, WebAssembly is now making the migration from the client side <a target="_blank" href="https://www.secondstate.io/articles/why-webassembly-server/">to the server side</a>.</p>
<p>Rust-in-WebAssembly bodes well with the trend of accelerating Rust adoption on backend web applications. You can get started with Rust and WebAssembly application development from a starter project in <a target="_blank" href="https://github.com/second-state/ssvm-nodejs-starter">this GitHub repository</a>.</p>
<h2 id="heading-asynchronous-programming-is-taking-off">? Asynchronous programming is taking off</h2>
<p>In recent years, two new programming languages have gained significant traction among developers. One is Rust, and the other is Go. A big part of their success is their superior support for concurrency programming models.</p>
<p>In fact, an early tagline of Rust is "fearless concurrency". It promises developer productivity in writing asynchronous multi-threaded programs optimized for today’s multi-core CPU architectures. As Node.js demonstrated, easy asynchronous programming is crucial for a language or framework’s success on the server side.</p>
<p>The survey shows that 4 of the 10 most important Rust crates (ie third party libraries), <a target="_blank" href="https://tokio.rs/">tokio</a>, <a target="_blank" href="https://docs.rs/crate/async-std/1.4.0">async</a>, <a target="_blank" href="https://docs.rs/futures/0.3.4/futures/">futures</a>, and <a target="_blank" href="https://hyper.rs/">hyper</a>, are frameworks for asynchronous multi-thread applications.</p>
<h2 id="heading-r-python-and-javascript">? R, Python, and JavaScript</h2>
<p>As the adoption of Rust grows, developers increasingly need to integrate Rust programs with programs written in other languages. In the past, C and C++ were the most common languages to “talk” to Rust as they are all used in infrastructure software projects.</p>
<p>As Rust grows into application software projects, more language level interfaces and bridges are needed now. A good example is the <a target="_blank" href="https://www.secondstate.io/articles/rust-functions-in-nodejs/">Rust JavaScript bridge</a> that supports <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">Rust functions in Node.js</a> applications.</p>
<p>The survey found that, besides C/C++ and JavaScript, Rust developers are interested in integrating with R and Python. That indicates developer interests in machine learning, big data, and artificial intelligence (AI) applications. In fact, many Python and R machine learning and statistical packages are implemented in native binary modules.</p>
<p>Rust is one of the best programming languages to write native modules. <a target="_blank" href="https://github.com/second-state/rust-wasm-ai-demo">This example</a> shows how to use <a target="_blank" href="https://www.secondstate.io/articles/artificial-intelligence/">Rust to execute Tensorflow models in a Node.js</a> application. In the future, we envision such Rust modules to run in high performance managed containers such as WebAssembly.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>2019 was a year of growth and incremental improvements for Rust. As Rust becomes a mainstream programming language, we look forward to more documentation, more tools, more ecosystem support, more interoperability with other languages, and a gentler learning curve.</p>
<p>And most important of all, we are eager to make more friends and have fun with the most beloved programming language in the world!</p>
<h2 id="heading-about-the-author">About the author</h2>
<p>Dr. Michael Yuan is the <a target="_blank" href="http://www.michaelyuan.com/">author of 5 books</a> on software engineering. His latest book <a target="_blank" href="https://www.buildingblockchainapps.com/">Building Blockchain Apps</a> was published by Addison-Wesley in Dec 2019. Dr. Yuan is the co-founder of <a target="_blank" href="https://www.secondstate.io/">Second State</a>, a VC-funded startup that brings WebAssembly and Rust technologies to <a target="_blank" href="https://www.secondstate.io/articles/why-webassembly-server/">cloud</a>, <a target="_blank" href="https://docs.secondstate.io/">blockchain</a>, and <a target="_blank" href="https://github.com/second-state/rust-wasm-ai-demo/blob/master/README.md">AI</a> applications. It enables developers to deploy fast, safe, portable, and serverless <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">Rust functions on Node.js</a>.</p>
<div class="embed-wrapper"><iframe src="https://webassemblytoday.substack.com/embed" width="480" height="320" style="border:1px solid #EEE;background:white" title="Embedded content" loading="lazy"></iframe></div>

<p>Prior to Second State, Dr. Yuan was a long time open source contributor at Red Hat, JBoss, and Mozilla. Outside of software, Dr. Yuan is a Principal Investigator at the National Institutes of Health, with multiple research awards on cancer and public health research. He holds a PhD in astrophysics from the University of Texas at Austin.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Learn Rust Without Installing Any Software ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll learn how to use GitHub Actions to learn Rust from your web browser. We'll code, build, test, run, and release all from a web page. No software needed! Learn with GitHub or follow us on Twitter. Rust is one of the hottest progr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-rust-with-github-actions/</link>
                <guid isPermaLink="false">66d4604c55db48792eed3f85</guid>
                
                    <category>
                        <![CDATA[ GitHub Actions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Michael Yuan ]]>
                </dc:creator>
                <pubDate>Tue, 24 Mar 2020 23:03:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.09.11-AM-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll learn how to use GitHub Actions to learn Rust from your web browser. We'll code, build, test, run, and release all from a web page. No software needed! <a target="_blank" href="https://github.com/second-state/learn-rust-with-github-actions">Learn with GitHub</a> or <a target="_blank" href="https://twitter.com/secondstateinc">follow us on Twitter</a>.</p>
<p>Rust is one of the hottest programming languages today. <a target="_blank" href="https://martinfowler.com/bliki/AlphaGeek.html">Alpha geeks</a> love it. It is Stackoverflow's <a target="_blank" href="https://www.theregister.co.uk/2019/04/09/stack_overflow_survey/">most beloved programming language</a> for the past 4 years in a row.</p>
<p>One of the most unique and beloved features of Rust is its aggressive compiler that helps you ensure correctness and safety before the program even runs. As a result, Rust developers can write highly performant yet safe programs. Rust eliminates whole classes of programming bugs, especially those hard-to-debug runtime bugs.</p>
<p>If you have not tried it, try it! <em>It is magical.</em> I believe Rust could be the next Java or Ruby -- the programming language everyone must learn in the future.</p>
<p>However, <a target="_blank" href="https://www.secondstate.io/articles/a-rusty-hello-world/">learning Rust</a> typically requires you to install a bunch of command line tools on your computer. The Rust compiler is slow because the whole Rust paradigm is set up to deeply analyze the source code and find bugs at compile time, instead of crashing at runtime.</p>
<p>Online Rust IDEs, like the <a target="_blank" href="https://play.rust-lang.org/">Rust Playground</a> and <a target="_blank" href="https://repl.it/languages/rust">REPL.it</a>, are simple tools that do not take full advantages of the Rust ecosystem of third party compiler targets and libraries.</p>
<p>So you might wonder - can I try and learn Rust without having to install all those software packages on my computer?</p>
<p>Well, with GitHub actions, you can! You can learn and experiment with Rust code directly in your web browser. Let's get started!</p>
<blockquote>
<p>GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want. The source code and workflow actions for the Hello World example can be found in <a target="_blank" href="https://github.com/second-state/learn-rust-with-github-actions">this GitHub repository</a>.</p>
</blockquote>
<h2 id="heading-hello-world">Hello world</h2>
<p>First, create a new GitHub repository, and add a Rust source file. Let's add a <code>src/main.rs</code> file with the following content.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"Hello, world!"</span>);
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.22.33-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, go back to the root <code>/</code> directory of the GitHub repository, and add a <code>Cargo.toml</code> file. This file describes how the Rust cargo system should build and package our project.</p>
<pre><code class="lang-toml"><span class="hljs-section">[package]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"hello"</span>
<span class="hljs-attr">version</span> = <span class="hljs-string">"0.1.0"</span>
<span class="hljs-attr">authors</span> = [<span class="hljs-string">"ubuntu"</span>]
<span class="hljs-attr">edition</span> = <span class="hljs-string">"2018"</span>

<span class="hljs-section">[dependencies]</span>
</code></pre>
<p>Now we have a complete Rust project. Let's build and run it now.</p>
<h2 id="heading-github-actions">Github actions</h2>
<p>On GitHub's Actions tab, we can add workflows associated with this project. Those are actions Github automatically performs when certain events occur, such as code push or commit. In our case, we would like GitHub to automatically build and run our <code>main.rs</code>, and show us the results.</p>
<p>The workflow actions and their event triggers are defined in <code>yml</code> files under the <code>.github/workflows</code> directory. You can write your own <code>yml</code> files, or pick from one of the ready-made templates.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.23.39-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The Rust workflow template in GitHub Actions</em></p>
<p>Here we choose the Rust template. GitHub allows you to edit the <code>rust.yml</code> file before checking it into the repository.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.24.16-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The default Rust actions template. You can edit it to your own liking.</em></p>
<p>Let's take a minute here to explain how GitHub Actions work. The default <code>rust.yml</code> file says that</p>
<ul>
<li><p>Whenever a user pushes code or accepts pull requests into this repository, the actions in this <code>rust.yml</code> workflow will be triggered.</p>
</li>
<li><p>The workflow will create a virtual machine running the latest Ubuntu operating system. On this Ubuntu system, it will then perform the following steps.</p>
</li>
<li><p>It will checkout the code from the <code>master</code> branch.</p>
</li>
<li><p>It will run the <code>cargo build --verbose</code> command to compile and build the Rust code.</p>
</li>
<li><p>It will run the <code>cargo test --verbose</code> command to execute the test cases.</p>
</li>
<li><p>All the standard and console outputs on the Ubuntu system from the above two commands will be captured by GitHub Actions and displayed on the web.</p>
</li>
</ul>
<p>You can edit the last line in <code>rust.yml</code> to perform <code>cargo run</code>, which runs the compiled binary program. Our updated <code>rust.yml</code> file is as follows.</p>
<pre><code class="lang-yml"><span class="hljs-attr">name:</span> <span class="hljs-string">Rust</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">master</span> ]
  <span class="hljs-attr">pull_request:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">master</span> ]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>

    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">cargo</span> <span class="hljs-string">build</span> <span class="hljs-string">--verbose</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">cargo</span> <span class="hljs-string">run</span>
</code></pre>
<p>Now whenever you push code to this repository, the actions in <code>rust.yml</code> are performed. You can see the results under the Actions tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.26.32-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Every push to the GitHub repo will trigger the actions to run</em></p>
<p>You can click on a result, and click on the build tab to the left to see the details. The build and run sections provide the most relevant details. The Run section shows successful printing of hello world!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.27.02-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The Run action shows Hello World! printed to the console!</em></p>
<p>Next, you can add third party dependencies in <code>Cargo.toml</code>, and build complex Rust applications in main.rs. Every time someone pushes code, we will be able to see the results.</p>
<h2 id="heading-test-driven-development-tdd">Test Driven Development (TDD)</h2>
<p>Of course, very few developers actually run their programs to print text to the console. The <code>cargo run</code> above is just a show. In reality, most developers write functions and test cases for those functions. The most frequent task after compiling and building is to run test cases. Let's see how it is done.</p>
<p>Create a new GitHub repository, and then add a <code>src/lib.rs</code> file below. As you can see, it defines a Rust function and a few test cases. It can be built and released as a Rust library package.</p>
<pre><code class="lang-rust"><span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">say</span></span>(s: &amp;<span class="hljs-built_in">str</span>) -&gt; <span class="hljs-built_in">String</span> {
  <span class="hljs-keyword">let</span> r = <span class="hljs-built_in">String</span>::from(<span class="hljs-string">"hello "</span>);
  <span class="hljs-keyword">return</span> r + s;
}

<span class="hljs-meta">#[cfg(test)]</span>
<span class="hljs-keyword">mod</span> tests {
  <span class="hljs-keyword">use</span> super::*;

  <span class="hljs-meta">#[test]</span>
  <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">say_hello</span></span>() {
    <span class="hljs-keyword">let</span> result = say(<span class="hljs-string">"ssvm"</span>);
    <span class="hljs-built_in">assert!</span>(result.contains(<span class="hljs-string">"hello ssvm"</span>));
  }
}
</code></pre>
<p>Then, go back to the root <code>/</code> directory of the GitHub repository, and add the following <code>Cargo.toml</code> file.</p>
<pre><code class="lang-toml"><span class="hljs-section">[package]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"hello"</span>
<span class="hljs-attr">version</span> = <span class="hljs-string">"0.1.0"</span>
<span class="hljs-attr">authors</span> = [<span class="hljs-string">"ubuntu"</span>]
<span class="hljs-attr">edition</span> = <span class="hljs-string">"2018"</span>

<span class="hljs-section">[lib]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"hello_lib"</span>
<span class="hljs-attr">path</span> = <span class="hljs-string">"src/lib.rs"</span>
<span class="hljs-attr">crate-type</span> =[<span class="hljs-string">"cdylib"</span>]

<span class="hljs-section">[dependencies]</span>
</code></pre>
<p>Click on the Actions tab and add the default Rust workflow. As you recall, the default Rust workflow ends with <code>cargo test</code>, which is exactly what we need here.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.24.16-AM-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The default Rust workflow actions are what we need here.</em></p>
<p>The workflow runs every time new code is pushed into this repository. You can click open a successful build, and see the output from the build and test actions.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-20-at-2.09.11-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Github actions build and test your Rust program</em></p>
<h2 id="heading-whats-next">What's next</h2>
<p>Now you can experiment with your Rust code, and have GitHub build, test, and run it for you with complete console outputs, for free and without ever leaving your browser!</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://www.rust-lang.org/learn">Learn to program in Rust</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/features/actions">Learn more about GitHub Actions</a></p>
</li>
<li><p>Of course, the best way to run Rust programs on the server is <a target="_blank" href="https://www.secondstate.io/articles/rust-and-webassembly/">inside a WebAssembly Virtual Machine</a>. Checkout the open source <a target="_blank" href="https://www.secondstate.io/">Second State VM</a> for that!</p>
</li>
<li><p>Learn about the <a target="_blank" href="https://www.secondstate.io/buidl/">BUIDL</a> online IDE to <a target="_blank" href="http://buidl.secondstate.io/">code and deploy</a> decentralized web apps on public blockchains</p>
</li>
</ul>
<h2 id="heading-about-the-author">About the author</h2>
<p>Dr. Michael Yuan is the <a target="_blank" href="http://www.michaelyuan.com/">author of 5 books</a> on software engineering. His latest book <a target="_blank" href="https://www.buildingblockchainapps.com/">Building Blockchain Apps</a> was published by Addison-Wesley in Dec 2019. Dr. Yuan is the co-founder of <a target="_blank" href="https://www.secondstate.io/">Second State</a>, a VC-funded startup that brings WebAssembly and Rust technologies to <a target="_blank" href="https://www.secondstate.io/articles/why-webassembly-server/">cloud</a>, <a target="_blank" href="https://docs.secondstate.io/">blockchain</a>, and <a target="_blank" href="https://github.com/second-state/rust-wasm-ai-demo/blob/master/README.md">AI</a> applications. It enables developers to deploy fast, safe, portable, and serverless <a target="_blank" href="https://www.secondstate.io/articles/getting-started-with-rust-function/">Rust functions on Node.js</a>.</p>
<div class="embed-wrapper"><iframe src="https://webassemblytoday.substack.com/embed" width="480" height="320" style="border:1px solid #EEE;background:white" title="Embedded content" loading="lazy"></iframe></div>

<p>Prior to Second State, Dr. Yuan was a long time open source contributor at Red Hat, JBoss, and Mozilla. Outside of software, Dr. Yuan is a Principal Investigator at the National Institutes of Health, with multiple research awards on cancer and public health research. He holds a PhD in astrophysics from the University of Texas at Austin.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
