<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shri</title>
    <description>The latest articles on DEV Community by Shri (@drone-ah).</description>
    <link>https://dev.to/drone-ah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3276906%2Fdc8ffc20-f574-43ac-a644-1d55a49803d0.jpg</url>
      <title>DEV Community: Shri</title>
      <link>https://dev.to/drone-ah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/drone-ah"/>
    <language>en</language>
    <item>
      <title>Publishing from hugo to dev.to</title>
      <dc:creator>Shri</dc:creator>
      <pubDate>Tue, 23 Sep 2025 08:30:54 +0000</pubDate>
      <link>https://dev.to/drone-ah/publishing-from-hugo-to-devto-2hkd</link>
      <guid>https://dev.to/drone-ah/publishing-from-hugo-to-devto-2hkd</guid>
      <description>&lt;p&gt;I have been pondering federating parts of my blog to &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt;

for a bit more visibility.&lt;/p&gt;
&lt;p&gt;However, I had a couple of issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With html (instead of markdown), it would not pick up the code blocks
correctly&lt;/li&gt;
&lt;li&gt;With markdown, it would render the relative links incorrectly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I really wanted was a way to render the hugo markdown into Jekyll style
(which is what forem wants) but with the links rendered.&lt;/p&gt;
&lt;p&gt;This was a little more complicated than I would have liked.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;p&gt;At a minimum, I wanted two main things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Render code blocks correctly&lt;/li&gt;
&lt;li&gt;Relative URLs should be rendered as absolute (because they won’t work on
dev.to)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pre-existing-solutions"&gt;Pre-existing Solutions&lt;/h2&gt;
&lt;p&gt;I found &lt;a href="https://github.com/maelvls/hudevto" rel="noopener noreferrer"&gt;hugodevto&lt;/a&gt;
 which looked promising
except:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not a fan of having to manually update hundreds of posts with the devto id&lt;/li&gt;
&lt;li&gt;Had a couple of fiddly bits to get it working (my plain text outputs had some
troubles for unknown reasons)&lt;/li&gt;
&lt;li&gt;It rendered image urls,
&lt;a href="https://github.com/maelvls/hudevto/issues/2#issuecomment-3302934120" rel="noopener noreferrer"&gt;but not regular urls.&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately though, it felt a bit bulkier than what I was looking for&lt;/p&gt;
&lt;h2 id="using-hugo"&gt;Using Hugo&lt;/h2&gt;
&lt;p&gt;I had &lt;a href="https://drone-ah.com/tags/hugo/" rel="noopener noreferrer"&gt;done enough work with hugo&lt;/a&gt;
 and
&lt;a href="https://drone-ah.com/tags/inscribe/" rel="noopener noreferrer"&gt;output formats&lt;/a&gt;
 to have a vague idea of how to make it work.&lt;/p&gt;
&lt;h3 id="limitations"&gt;Limitations&lt;/h3&gt;
&lt;p&gt;There are a few limitations to doing it this way though. Hugo
&lt;a href="https://gohugo.io/render-hooks/introduction/" rel="noopener noreferrer"&gt;does not provide render hooks for everything&lt;/a&gt;
.
You will end up with html in the output. However, since Forem (and Jekyll) will
just render them, it fits my use case. It won’t work as well if you try and use
this to generate like for like markdown usable in Jekyll.&lt;/p&gt;
&lt;h3 id="define-a-new-content-type"&gt;Define a new content type&lt;/h3&gt;
&lt;p&gt;We want a new content type which will output markdown&lt;/p&gt;


```toml
[outputFormats.jekyll]
    mediaType = "text/markdown"
    baseName = "index"
    isPlainText = true
    isHTML = false
    notAlternative = true
    path = 'jekyll'        # put the output in `public/jekyll` so it's easier to find

[outputs]
    page = ['html', 'jekyll'] # Output all pages in our jekyll format as well
```


&lt;p&gt;You also need a basic template before hugo will output our markdown files.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/drone-ah/wordsonsand/blob/dc753f20a8d932a4bdb36378efb7bc5f3bf6cb1d/blog/layouts/_default/single.jekyll.md" rel="noopener noreferrer"&gt;&lt;code&gt;layouts/_default/single.jekyll.md&lt;/code&gt;&lt;/a&gt;
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
title: {{ .Title }}
published: true
date: {{ .Date }}
{{- with .Params.tags }}
tags: [{{ delimit . ", " }}]
{{- end }}
canonical_url: {{ .Permalink }}
---

{{ .Content }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, if you &lt;code&gt;hugo build&lt;/code&gt;, it’ll render the &lt;code&gt;.md&lt;/code&gt; files, but the content
will be html.&lt;/p&gt;
&lt;h3 id="render-code-blocks-as-markdown"&gt;Render code blocks as markdown&lt;/h3&gt;
&lt;p&gt;We can use the
&lt;a href="https://gohugo.io/render-hooks/code-blocks/" rel="noopener noreferrer"&gt;code block render hook&lt;/a&gt;
 to
“convert them” back to markdown.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/drone-ah/wordsonsand/blob/dc753f20a8d932a4bdb36378efb7bc5f3bf6cb1d/blog/layouts/_default/_markup/render-codeblock.jekyll.md" rel="noopener noreferrer"&gt;&lt;code&gt;layouts/_default/_markup/render-codeblock.jekyll.md&lt;/code&gt;&lt;/a&gt;
&lt;/p&gt;



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

&lt;/div&gt;



&lt;p&gt;{{ .Type }}&lt;br&gt;
{{ .Inner }}&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3 id="render-absolute-urls"&gt;Render absolute urls&lt;/h3&gt;

&lt;p&gt;I already have a pretty extensive
&lt;a href="https://github.com/drone-ah/wordsonsand/blob/dc753f20a8d932a4bdb36378efb7bc5f3bf6cb1d/blog/layouts/_default/_markup/render-link.html" rel="noopener noreferrer"&gt;&lt;code&gt;render-link&lt;/code&gt;&lt;/a&gt;
 so updating
it was just a case of making a copy of it and replacing relative url references
with absolute ones.&lt;/p&gt;
&lt;p&gt;It’s fine for it to be in html because Forem will still render it correctly.
They could be rendered as markdown and it should work just as well.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/drone-ah/wordsonsand/blob/dc753f20a8d932a4bdb36378efb7bc5f3bf6cb1d/blog/layouts/_default/_markup/render-link.jekyll.md" rel="noopener noreferrer"&gt;&lt;code&gt;layouts/_default/_markup/render-link.jekyll.md&lt;/code&gt;&lt;/a&gt;
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{ /* other content */ }}
  &amp;lt;a href="{{ printf "%s#%s" .PageInner.Permalink $u.Fragment | safeURL }}" {{ with .Title }}title="{{ . }}"{{ end }}&amp;gt;{{ $text }}&amp;lt;/a&amp;gt;
{{ /* other content */ }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3 id="output"&gt;Output&lt;/h3&gt;

&lt;p&gt;With these relatively minor changes, I was able to render markdown files I could
then pop into dev.to and it works for the handful I set up.&lt;/p&gt;

&lt;h2 id="next-steps"&gt;Next Steps&lt;/h2&gt;

&lt;h3 id="images"&gt;Images&lt;/h3&gt;

&lt;p&gt;One big glaring omission is images - it’s not as relevant for me because I
rarely use images.&lt;/p&gt;

&lt;p&gt;I expect it to be easy enough to use the
&lt;a href="https://gohugo.io/render-hooks/images/" rel="noopener noreferrer"&gt;image render hook&lt;/a&gt;
 to achieve this.&lt;/p&gt;

&lt;h3 id="tags"&gt;Tags&lt;/h3&gt;

&lt;p&gt;One of the issues I have is that dev.to has a strict tag limit of four.
Currently I manually edit that when I create the post on dev.to.&lt;/p&gt;

&lt;p&gt;It would be better to have a &lt;code&gt;devto_tags&lt;/code&gt; field because my local content tags
aren’t always relevant for dev.to.&lt;/p&gt;

&lt;p&gt;I could also write a script to automate the setting of the &lt;code&gt;devto_tags&lt;/code&gt; field
automatically based on the first four tags, and mapping from my tags to dev.to
tags if necessary by building a small map data set somewhere.&lt;/p&gt;

&lt;h3 id="automation"&gt;Automation&lt;/h3&gt;

&lt;p&gt;Once the above two are done, it would be good to automate it. I could&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.forem.com/api/v0#tag/articles/operation/getUserAllArticles" rel="noopener noreferrer"&gt;get all the posts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;get all the local posts&lt;/li&gt;
&lt;li&gt;map them based on the canonical url (which is returned by the endpoint)&lt;/li&gt;
&lt;li&gt;upload updated ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not all my posts are technical, so I’d also want to add a field to the
frontmatter (&lt;code&gt;devto_published&lt;/code&gt;) and figure out a way to push updates only if
there are changes.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I have a working solution for now - and if dev.to brings enough traffic / value,
then I’ll consider spending a bit more time adding polish.&lt;/p&gt;

&lt;p&gt;For the time being though, seems to work!&lt;/p&gt;

&lt;p&gt;Feel free to use any of this code (such that it is) as you wish.&lt;/p&gt;

</description>
      <category>wordsonsand</category>
      <category>hugo</category>
      <category>devto</category>
    </item>
    <item>
      <title>Using `locateFile` to have js and wasm in different locations with emscripten</title>
      <dc:creator>Shri</dc:creator>
      <pubDate>Thu, 18 Sep 2025 09:15:42 +0000</pubDate>
      <link>https://dev.to/drone-ah/using-locatefile-to-have-js-and-wasm-in-different-locations-with-emscripten-2koi</link>
      <guid>https://dev.to/drone-ah/using-locatefile-to-have-js-and-wasm-in-different-locations-with-emscripten-2koi</guid>
      <description>&lt;p&gt;Originally published &lt;a href="https://drone-ah.com/2025/09/17/calling-javascript-from-zig-through-webassembly/" rel="noopener noreferrer"&gt;at drone-ah.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As part of building &lt;a href="//../../excursions/shine.md"&gt;shine&lt;/a&gt;, I am using&lt;br&gt;
&lt;a href="https://lume.land" rel="noopener noreferrer"&gt;lume&lt;/a&gt; and webassembly with zig.&lt;/p&gt;

&lt;p&gt;zig, through emscripten generates both a js and wasm file, which, by default are&lt;br&gt;
expected to be in the same directory.&lt;/p&gt;

&lt;p&gt;I wanted to put them in different places, and struggled to get that working with&lt;br&gt;
lume for a bit. I did eventually solve it though:&lt;/p&gt;
&lt;h2&gt;
  
  
  Include emscripten js file
&lt;/h2&gt;

&lt;p&gt;Firstly, the js file output from emscripten should be included in you page&lt;br&gt;
manually. I had used &lt;code&gt;site.add&lt;/code&gt; which meant that it was loaded &lt;em&gt;before&lt;/em&gt; we could&lt;br&gt;
put the override for &lt;code&gt;locateFile&lt;/code&gt; in &lt;code&gt;window.Module&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I am using the&lt;br&gt;
&lt;a href="https://github.com/lumeland/theme-simple-blog" rel="noopener noreferrer"&gt;simple-blog theme&lt;/a&gt;, so I add the&lt;br&gt;
following line to the top of &lt;code&gt;src/index.vto&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/js/shine.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Override &lt;code&gt;Module&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You can override how emscripten finds the wasm file in the&lt;br&gt;
&lt;a href="https://emscripten.org/docs/api_reference/module.html#Module.locateFile" rel="noopener noreferrer"&gt;Module Object&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This can be done in the html file in a script block, or even better, in a js&lt;br&gt;
file that is included automatically.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;js/main.js&lt;/code&gt; felt like a good place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;locateFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scriptDirectory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shine.wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/static/shine/shine.wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;scriptDirectory&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;With this setup, I can not only have the js and wasm files in different&lt;br&gt;
locations, it's also easy to modify / augment the &lt;code&gt;Module&lt;/code&gt; object.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tooling</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Calling Javascript from Zig through WebAssembly</title>
      <dc:creator>Shri</dc:creator>
      <pubDate>Wed, 17 Sep 2025 14:52:20 +0000</pubDate>
      <link>https://dev.to/drone-ah/calling-javascript-from-zig-through-webassembly-2hdf</link>
      <guid>https://dev.to/drone-ah/calling-javascript-from-zig-through-webassembly-2hdf</guid>
      <description>&lt;p&gt;The next step for 
   &lt;span&gt;shine&lt;/span&gt;
   is to build a bridge
   between &lt;a href="/tags/zig/"&gt;zig&lt;/a&gt;
   and &lt;a href="/tags/javascript/"&gt;javascript&lt;/a&gt;
   .
&lt;/p&gt;

&lt;p&gt;I am currently planning to using &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;supabase&lt;/a&gt;
   for storage.
   Unsurprisingly, it does not have a zig sdk. It does, however, have a javascript
   sdk.
&lt;/p&gt;

&lt;p&gt;If I can write basic CRUD operations in javascript and call that from zig
   through webassembly, that could make that integration a lot easier.
&lt;/p&gt;

&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;

&lt;p&gt;There are a few ideal restrictions for me - mainly because writing javascript is
   not fun for me.
&lt;/p&gt;

&lt;ul&gt;
   &lt;li&gt;Use the Supabase js/ts library through zig&lt;/li&gt;
   &lt;li&gt;Use TypeScript as much as possible. (I don’t love TypeScript, but at least
      it’s not javascript)
   &lt;/li&gt;
   &lt;li&gt;Keep as much of the supabase related code in the web part so that
      &lt;a href="/tags/deno/"&gt;deno&lt;/a&gt;
      and &lt;a href="/tags/lume/"&gt;lume&lt;/a&gt;
      can handle any heavy lifting.
   &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="options"&gt;Options&lt;/h2&gt;

&lt;p&gt;I can’t use FFI(Foreign Function Interface):&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extern "env" fn jsLog(ptr: [*]const u8, len: usize) void;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"env"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wasm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiateStreaming&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prog.wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cm"&gt;/* read from memory and console.log */&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because imgui pulls in emscripten, which means we don’t have the ability to call
   &lt;code&gt;instantiateStreaming&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;With emscripten, declaring an external function is easy enough.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple of options to wire them up to the javascript:&lt;/p&gt;

&lt;h3 id="libraryjs--mergeinto"&gt;
&lt;code&gt;library.js&lt;/code&gt; / &lt;code&gt;mergeInto&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This option requires javascript files on the zig side. If you want to start with
   typescript, you’ll need to integrate a transpiler into the build chain as well.
&lt;/p&gt;

&lt;p&gt;First, you want a javascript file - let’s call it &lt;code&gt;libshine.js&lt;/code&gt;, and pop it into
   a &lt;code&gt;js&lt;/code&gt; dir.
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// js/libshine.js&lt;/span&gt;
&lt;span class="c1"&gt;// Emscripten will provide these globals at link/runtime&lt;/span&gt;
&lt;span class="nx"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;mergeInto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;LibraryManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UTF8ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;mergeInto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LibraryManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UTF8ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🟢 Zig says:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then need to pass this &lt;code&gt;js&lt;/code&gt; file into the build step&lt;/p&gt;

&lt;p&gt;as part of my sokol build step, I pass it in as &lt;code&gt;.extra_args&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="c"&gt;// create a build step which invokes the Emscripten linker&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;link_step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;sokol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emLinkStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;lib_main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mod_main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;resolved_target&lt;/span&gt;&lt;span class="o"&gt;.?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;optimize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mod_main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;.?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;emsdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep_emsdk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;use_webgl2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;use_emmalloc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;use_filesystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;shell_file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;dep_sokol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/sokol/web/shell.html"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="c"&gt;// set the js file here&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;extra_args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="s"&gt;"--js-library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"js/libshine.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then call it from zig, with something like:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello from zig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From my firefox console:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lume live reloading is ready. Listening for changes...     localhost:3000:102:15
🟢 Zig says: hello from zig                                shine.js:3168:11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3 id="em_js--em_asm"&gt;
&lt;code&gt;EM_JS&lt;/code&gt; / &lt;code&gt;EM_ASM&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The other option is to use
   &lt;a href="https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-call-javascript-from-native" rel="noopener noreferrer"&gt;&lt;code&gt;EM_JS&lt;/code&gt;&lt;/a&gt;
   which involves writing a wee bit of &lt;code&gt;C&lt;/code&gt;, which can embed the &lt;code&gt;javascript&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;In theory, it’s as simple as:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; 
&lt;span class="cpf"&gt;&amp;lt;emscripten.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="n"&gt;EM_JS_DEPS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bla&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"$UTF8ToString"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;EM_JS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UTF8ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and adding it into the build file:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="c"&gt;// build the main file into a library, this is because the WASM 'exe'&lt;/span&gt;
&lt;span class="c"&gt;// needs to be linked in a separate build step with the Emscripten linker&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;shine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLibrary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"shine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;root_module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mod_main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c"&gt;// get the Emscripten SDK dependency from the sokol dependency&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;dep_emsdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;dep_sokol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"emsdk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="c"&gt;// need to inject the Emscripten system header include path into&lt;/span&gt;
&lt;span class="c"&gt;// the cimgui C library otherwise the C/C++ code won't find&lt;/span&gt;
&lt;span class="c"&gt;// C stdlib headers&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;emsdk_incl_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep_emsdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"upstream/emscripten/cache/sysroot/include"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;shine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;root_module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCSourceFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/libjs.c"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;.&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="c"&gt;// optional extra emcc flags&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="n"&gt;shine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSystemIncludePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emsdk_incl_path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The calling code in &lt;code&gt;main.zig&lt;/code&gt; remains the same:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello from zig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this didn’t work, and failed with:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: undefined symbol: jsLog (referenced by root reference (e.g. compiled C/C++ code))
warning: To disable errors for undefined symbols use `-sERROR_ON_UNDEFINED_SYMBOLS=0`
warning: _jsLog may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
Error: Aborting compilation due to previous errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to
   &lt;a href="https://ziggit.dev/t/help-with-getting-a-simple-call-to-js-through-emscripten-working/12090/3" rel="noopener noreferrer"&gt;some help&lt;/a&gt;
   from &lt;a href="https://ziggit.dev/u/floooh" rel="noopener noreferrer"&gt;flooh&lt;/a&gt;
   (who btw put together the
   &lt;a href="https://github.com/floooh/sokol" rel="noopener noreferrer"&gt;sokol&lt;/a&gt;
   and
   &lt;a href="https://github.com/floooh/sokol-zig" rel="noopener noreferrer"&gt;sokol-zig&lt;/a&gt;
   packages as well the
   &lt;a href="https://github.com/floooh/sokol-zig-imgui-sample" rel="noopener noreferrer"&gt;sokol-imgui-sample&lt;/a&gt;
   template
   which I used to kick start this project.), I was able to get it working.
&lt;/p&gt;

&lt;p&gt;Turns out the c file needs to have a function in it that is used in the zig
   file - it doesn’t need to do anything.
&lt;/p&gt;

&lt;p&gt;So, based on the suggestion, &lt;code&gt;libjs.c&lt;/code&gt; changes to:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; 
&lt;span class="cpf"&gt;&amp;lt;emscripten.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="n"&gt;EM_JS_DEPS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bla&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"$UTF8ToString"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;EM_JS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UTF8ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and in &lt;code&gt;main.zig&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello from zig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From my firefox console:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lume live reloading is ready. Listening for changes...     localhost:3000:102:15
🟢 Zig says: hello from zig                                shine.js:3168:11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a working example in [my forked repo](&lt;/p&gt;

&lt;h2 id="em_js-directly-through-zig-unsuccessful"&gt;
&lt;code&gt;EM_JS&lt;/code&gt; directly through &lt;code&gt;zig&lt;/code&gt; [unsuccessful]&lt;/h2&gt;

&lt;p&gt;Looking at the macro for &lt;code&gt;EM_JS&lt;/code&gt; and with my good friend ChatGPT, I attempted
   translating it to zig and made some progress, but ultimately failed to get it
   working. I’ll leave the work here in the hopes it might be helpful.
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define _EM_JS(ret, c_name, js_name, params, code)                             \
_EM_BEGIN_CDECL                                                              \
ret c_name params EM_IMPORT(js_name);                                        \
__attribute__((visibility("hidden")))                                        \
void* __em_js_ref_##c_name = (void*)&amp;amp;c_name;                                 \
EMSCRIPTEN_KEEPALIVE                                                         \
__attribute__((section("em_js"), aligned(1))) char __em_js__##js_name[] =    \
#params "
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;::&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;" code;                                                       \
_EM_END_CDECL&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above macro translates to zig roughly (with help from ChatGPT) as:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;/// 2. Keep a reference to avoid the linker removing the function.&lt;/span&gt;
&lt;span class="c"&gt;///    Same role as __em_js_ref_* in the C macro.&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="mi"&gt;__&lt;/span&gt;&lt;span class="n"&gt;em_js_ref_jsLog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;/// 3. Embed the JS implementation in a special section called "em_js".&lt;/span&gt;
&lt;span class="c"&gt;///    Emscripten will scan this and inject the code into the output JS.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="mi"&gt;__&lt;/span&gt;&lt;span class="n"&gt;em_js__jsLog&lt;/span&gt; &lt;span class="k"&gt;align&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;linksection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"em_js"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="s"&gt;"(const char* s)
&amp;lt;::&amp;gt;
{ console.log(UTF8ToString(s)); }&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added a &lt;code&gt;pub fn&lt;/code&gt; and called it from main:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which gave me the familiar error about not being able to find &lt;code&gt;jsLog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;comparing the linker sections gave some clues:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ wasm-objdump --section=linking -x &amp;lt;path/to/libjs.o&amp;gt;
libjs.o:        file format wasm 0x1
Section Details:
Custom:
- name: "linking"
- symbol table [count=9]
- 0: F 
&amp;lt;dummy&amp;gt;
func=1 [ binding=global vis=hidden ]
- 1: D 
&amp;lt;__em_js_ref_jsLog&amp;gt;
segment=0 offset=0 size=4 [ binding=global vis=hidden ]
- 2: F 
&amp;lt;jsLog&amp;gt;
func=0 [ undefined explicit_name binding=global vis=default ]
- 3: D 
&amp;lt;__em_js__jsLog&amp;gt;
segment=1 offset=0 size=53 [ exported no_strip binding=global vis=hidden ]
- 4: S &amp;lt;.debug_abbrev&amp;gt; section=7 [ binding=local vis=default ]
- 5: G 
&amp;lt;env.__stack_pointer&amp;gt;
global=0 [ undefined binding=global vis=default ]
- 6: S &amp;lt;.debug_str&amp;gt; section=9 [ binding=local vis=default ]
- 7: T 
&amp;lt;env.__indirect_function_table&amp;gt;
table=0 [ undefined exported no_strip binding=global vis=default ]
- 8: S &amp;lt;.debug_line&amp;gt; section=10 [ binding=local vis=default ]
- segment info [count=2]
- 0: .data.__em_js_ref_jsLog p2align=2 [ ]
- 1: em_js p2align=0 [ RETAIN ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the zig object:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ wasm-objdump --section=linking -x js.o
js.o:   file format wasm 0x1
Section Details:
Custom:
- name: "linking"
- symbol table [count=6]
- 0: F 
&amp;lt;dummy&amp;gt;
func=1 [ binding=global vis=default ]
- 1: D 
&amp;lt;__em_js_ref_jsLog&amp;gt;
segment=0 offset=0 size=4 [ binding=global vis=default ]
- 2: F 
&amp;lt;jsLog&amp;gt;
func=0 [ undefined explicit_name binding=global vis=default ]
- 3: D 
&amp;lt;__em_js__jsLog&amp;gt;
segment=1 offset=0 size=4 [ binding=global vis=default ]
- 4: D 
&amp;lt;__anon_946&amp;gt;
segment=2 offset=0 size=54 [ binding=local vis=default ]
- 5: T 
&amp;lt;env.__indirect_function_table&amp;gt;
table=0 [ undefined exported no_strip binding=global vis=default ]
- segment info [count=3]
- 0: .rodata.__em_js_ref_jsLog p2align=2 [ ]
- 1: em_js p2align=0 [ ]
- 2: .rodata.__anon_946 p2align=0 [ ]`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From what I could understand (which is little), it looks like &lt;code&gt;__em_js__jsLog&lt;/code&gt;
   in the zig obj is a pointer while from C, it’s the full string.
&lt;/p&gt;

&lt;p&gt;hardcoding it as a static array helped:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="mi"&gt;__&lt;/span&gt;&lt;span class="n"&gt;em_js__jsLog&lt;/span&gt; &lt;span class="k"&gt;align&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;linksection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"em_js"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="sc"&gt;'('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'o'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'h'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;')'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="sc"&gt;'&amp;lt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'o'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'o'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'l'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'l'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'o'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'g'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="sc"&gt;'U'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'T'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'8'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'T'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'o'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'S'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'i'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'g'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="sc"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;')'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;')'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;';'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'\x00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output from this is a little more promising&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ wasm-objdump --section=linking -x js.o
js.o:   file format wasm 0x1
Section Details:
Custom:
- name: "linking"
- symbol table [count=5]
- 0: F 
&amp;lt;dummy&amp;gt;
func=1 [ binding=global vis=default ]
- 1: D 
&amp;lt;__em_js_ref_jsLog&amp;gt;
segment=0 offset=0 size=4 [ binding=global vis=default ]
- 2: F 
&amp;lt;jsLog&amp;gt;
func=0 [ undefined explicit_name binding=global vis=default ]
- 3: D 
&amp;lt;__em_js__jsLog&amp;gt;
segment=1 offset=0 size=53 [ binding=global vis=default ]
- 4: T 
&amp;lt;env.__indirect_function_table&amp;gt;
table=0 [ undefined exported no_strip binding=global vis=default ]
- segment info [count=2]
- 0: .rodata.__em_js_ref_jsLog p2align=2 [ ]
- 1: em_js p2align=0 [ ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s look at the two side by side&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# From C
- 3: D 
&amp;lt;__em_js__jsLog&amp;gt;
segment=1 offset=0 size=53 [ exported no_strip binding=global vis=hidden ]
# From zig
- 3: D 
&amp;lt;__em_js__jsLog&amp;gt;
segment=1 offset=0 size=53 [ binding=global vis=default ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some clear differences in how the two are output and I am already
   beyond my knowledge level here - so I’ll leave it to someone who knows this
   stuff better (or wait until I do)
&lt;/p&gt;

&lt;p&gt;You can
   &lt;a href="https://github.com/drone-ah/sokol-zig-imgui-sample/tree/zig_em_js" rel="noopener noreferrer"&gt;check out the code in the branch of my forked repo&lt;/a&gt;
&lt;/p&gt;

&lt;h2 id="next-steps"&gt;Next steps&lt;/h2&gt;

&lt;p&gt;My plan is to use &lt;code&gt;EM_JS&lt;/code&gt; through &lt;code&gt;C&lt;/code&gt; to implement glue JavaScript functions -
   something like:
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;EM_JS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UTF8ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, I can have one-line js code in the &lt;code&gt;.c&lt;/code&gt; file and all the
   implementation can go into the web side (and can easily be TypeScript too).
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;jsLog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🟢 Zig says:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>zig</category>
      <category>webassembly</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Auto reload WASM with zig+lume</title>
      <dc:creator>Shri</dc:creator>
      <pubDate>Wed, 17 Sep 2025 11:20:51 +0000</pubDate>
      <link>https://dev.to/drone-ah/auto-reload-wasm-with-ziglume-31ag</link>
      <guid>https://dev.to/drone-ah/auto-reload-wasm-with-ziglume-31ag</guid>
      <description>&lt;p&gt;I’ve been taking some time off to rest and recover from health issues that made&lt;br&gt;
it hard to focus. To ease back in, I’ve started a small project:&lt;br&gt;
&lt;a href="//../../excursions/shine.md"&gt;shine&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project would do well to be multiplatform - mobile and web. The obvious&lt;br&gt;
choice was &lt;a href="https://dev.to/tags/flutter"&gt;flutter&lt;/a&gt; and I have enjoyed working with it before.&lt;/p&gt;

&lt;p&gt;However, as I'm currently in love with &lt;a href="https://dev.to/tags/zig"&gt;zig&lt;/a&gt;, I wanted to work with&lt;br&gt;
that instead.&lt;/p&gt;
&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Graphics
&lt;/h3&gt;

&lt;p&gt;I've been playing with &lt;a href="https://dev.to/tags/raylib"&gt;raylib&lt;/a&gt; and that was my initial instinct.&lt;br&gt;
However, raylib&lt;br&gt;
&lt;a href="https://github.com/raysan5/raylib/discussions/2681" rel="noopener noreferrer"&gt;does not support iOs&lt;/a&gt; and&lt;br&gt;
&lt;a href="https://github.com/raysan5/raylib/discussions/3626" rel="noopener noreferrer"&gt;has issues with wasm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I considered a few options, including&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.libsdl.org/" rel="noopener noreferrer"&gt;sdl&lt;/a&gt;, which looked great but was perhaps a little
too low level for me.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Jack-Ji/jok" rel="noopener noreferrer"&gt;jok&lt;/a&gt; - does not support mobile and possibly
has a little more than I needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, I decided to go with &lt;a href="https://github.com/floooh/sokol" rel="noopener noreferrer"&gt;sokol&lt;/a&gt; and&lt;br&gt;
&lt;a href="https://github.com/floooh/sokol-zig" rel="noopener noreferrer"&gt;sokol-zig&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While a little more lower level than raylib, it has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a modern clean api&lt;/li&gt;
&lt;li&gt;first class mobile support&lt;/li&gt;
&lt;li&gt;first class wasm support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  UI
&lt;/h3&gt;

&lt;p&gt;I've been working with &lt;a href="https://dev.to/tags/dvui"&gt;dvui&lt;/a&gt; a lot recently. Unfortunately, it&lt;br&gt;
doesn't support sokol. &lt;a href="https://github.com/SpexGuy/Zig-ImGui" rel="noopener noreferrer"&gt;imgui&lt;/a&gt; is a better&lt;br&gt;
option.&lt;/p&gt;

&lt;p&gt;There is even a&lt;br&gt;
&lt;a href="https://github.com/floooh/sokol-zig-imgui-sample" rel="noopener noreferrer"&gt;template project that I could start from&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  WASM first
&lt;/h2&gt;

&lt;p&gt;To keep things straightforward, I decided to start with wasm. If I make the site&lt;br&gt;
mobile friendly, I could see how it goes and see if it needs a mobile version.&lt;/p&gt;

&lt;p&gt;I will need some shared data storage and have been considering&lt;br&gt;
&lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;supabase&lt;/a&gt;, which has &lt;a href="https://dev.to/tags/javascript"&gt;javascript&lt;/a&gt;&lt;br&gt;
libs. By using &lt;a href="https://dev.to/tags/wasm"&gt;wasm&lt;/a&gt;, I can effectively shim in js functions to&lt;br&gt;
handle that instead of having to write bare rest calls from zig.&lt;/p&gt;
&lt;h3&gt;
  
  
  Structuring the project
&lt;/h3&gt;

&lt;p&gt;Is this a zig project with a web component, vice versa or indeed two independent&lt;br&gt;
parts that work together.&lt;/p&gt;

&lt;p&gt;I did a fair amount of web searching to see if there was some guidance I could I&lt;br&gt;
find for a good way to structure a relatively straightforward zig+js project.&lt;/p&gt;

&lt;p&gt;I could not find one. In the end, I decided to keep it fairly straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- shine/
  - src/ # zig code
  - web/ # all the web stuff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;After a bit of research, and realising that I will probably need a little bit of&lt;br&gt;
supporting content around &lt;a href="//../../excursions/shine.md"&gt;shine&lt;/a&gt;, I decided to go&lt;br&gt;
with &lt;a href="https://lume.land/" rel="noopener noreferrer"&gt;lume&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used the &lt;a href="https://github.com/lumeland/theme-simple-blog" rel="noopener noreferrer"&gt;simple-blog theme&lt;/a&gt; as&lt;br&gt;
a template to start from. I could have just pulled the template in but I wanted&lt;br&gt;
a custom homepage.&lt;/p&gt;

&lt;p&gt;When I tried to add an &lt;code&gt;index.md&lt;/code&gt;, it complained about two files wanting to&lt;br&gt;
write &lt;code&gt;index.html&lt;/code&gt;. From what I could find, the easiest way to override the&lt;br&gt;
homepage was to just pick up the theme and edit it - which was easy enough.&lt;/p&gt;
&lt;h3&gt;
  
  
  WASM =&amp;gt; frontend
&lt;/h3&gt;

&lt;p&gt;I didn't want to copy over the wasm and the js file every time, so I added a&lt;br&gt;
couple of steps to &lt;code&gt;build.zig&lt;/code&gt; right after the &lt;code&gt;link_step&lt;/code&gt; (also included below)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="c"&gt;// build.zig&lt;/span&gt;
&lt;span class="c"&gt;// create a build step which invokes the Emscripten linker&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;link_step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;sokol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emLinkStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;lib_main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mod_main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;resolved_target&lt;/span&gt;&lt;span class="o"&gt;.?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;optimize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mod_main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;.?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;emsdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dep_emsdk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;use_webgl2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;use_emmalloc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;use_filesystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;shell_file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;dep_sokol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/sokol/web/shell.html"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c"&gt;// attach to default target&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstallStep&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;dependOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;link_step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;step&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c"&gt;// Copy shine.js from default emscripten output&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;js_install&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInstallFileWithDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"zig-out/web/shine.js"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;custom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../web/src/static/shine"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;"shine.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;js_install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dependOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;link_step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;step&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstallStep&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;dependOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;js_install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;step&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c"&gt;// Copy shine.wasm from default emscripten output&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;wasm_install&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInstallFileWithDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"zig-out/web/shine.wasm"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;custom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../web/src/static/shine"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;"shine.wasm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;wasm_install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dependOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;link_step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;step&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These steps will copy across the wasm and the js file across to &lt;code&gt;static/shine&lt;/code&gt;.&lt;br&gt;
I wanted to put the js in &lt;code&gt;src/js&lt;/code&gt; and the wasm in the static dir. However, the&lt;br&gt;
js file expects the wasm in the same dir. I tried overriding &lt;code&gt;locateFile&lt;/code&gt; but it&lt;br&gt;
didn't work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- index.vto --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;locateFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/static/shine/shine.wasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/js/shine.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was able to get lume to process the javascript file by &lt;code&gt;add&lt;/code&gt;ing it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// _config.ts&lt;/span&gt;
&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;static/shine/shine.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With all of these set up, I was able to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zig build &lt;span class="nt"&gt;-Dtarget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wasm32-emscripten &lt;span class="nt"&gt;--watch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in one window. This command will rebuild wasm and provide it to lume whenever&lt;br&gt;
the zig code changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deno task serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this in another window will mean that lume will rebuild on any changes,&lt;br&gt;
including a new wasm file and redeploy. The redeploy will trigger an auto-reload&lt;br&gt;
of the page as well if I have it in a browser.&lt;/p&gt;

&lt;p&gt;I now effectively have automated reload with changes if I make changes in either&lt;br&gt;
zig or the frontend.&lt;/p&gt;

&lt;p&gt;I don't have &lt;em&gt;hot&lt;/em&gt; reload - but this is pretty good for now.&lt;/p&gt;

</description>
      <category>zig</category>
      <category>webassembly</category>
      <category>lume</category>
    </item>
    <item>
      <title>Building Pong in Zig with Raylib – Part 1: Setup, Paddles, and Ball</title>
      <dc:creator>Shri</dc:creator>
      <pubDate>Sat, 28 Jun 2025 19:38:29 +0000</pubDate>
      <link>https://dev.to/drone-ah/building-pong-in-zig-with-raylib-part-1-setup-paddles-and-ball-119l</link>
      <guid>https://dev.to/drone-ah/building-pong-in-zig-with-raylib-part-1-setup-paddles-and-ball-119l</guid>
      <description>&lt;p&gt;Before continuing development on Triangle - my larger, arcade ARPG, factory
game, I wanted to take a step back and build something small and familiar. Pong
felt like the perfect choice: quick to prototype, easy to understand, and a good
warm-up before diving deeper into raylib again.&lt;/p&gt;

&lt;p&gt;This post goes alongside &lt;a href="https://youtu.be/ICq2D_na6zc" rel="noopener noreferrer"&gt;my video on YouTube&lt;/a&gt;
,
and walks through the early steps of the project: setting up the game, getting
something on screen, and implementing the paddles and the ball.&lt;/p&gt;

&lt;h2 id="why-pong"&gt;Why Pong?&lt;/h2&gt;

&lt;p&gt;Sometimes, before getting deeper into a project, it helps to do something simple
just to get your hands moving again. I hadn’t written Zig in a couple of weeks,
and wanted a fast feedback loop to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get back into using &lt;code&gt;raylib-zig&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Have a bit of fun&lt;/li&gt;
&lt;li&gt;Remind myself why I made certain decisions in the first place&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="project-setup"&gt;Project Setup&lt;/h2&gt;

&lt;p&gt;I’m using &lt;a href="https://github.com/Not-Nik/raylib-zig" rel="noopener noreferrer"&gt;&lt;code&gt;raylib-zig&lt;/code&gt;&lt;/a&gt;
 for this. You
can scaffold a new project with:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./project_setup.sh &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could also use &lt;code&gt;zig init&lt;/code&gt; and then add the dependency in manually if you
prefer.&lt;/p&gt;

&lt;h2 id="drawing-the-playground"&gt;Drawing the Playground&lt;/h2&gt;

&lt;p&gt;The Pong “arena” is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two paddles&lt;/li&gt;
&lt;li&gt;A ball (currently static)&lt;/li&gt;
&lt;li&gt;A center dividing line&lt;/li&gt;
&lt;li&gt;Placeholder for scores&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="implementing-paddles"&gt;Implementing Paddles&lt;/h2&gt;

&lt;p&gt;The paddles have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A position (top-left corner)&lt;/li&gt;
&lt;li&gt;A fixed size&lt;/li&gt;
&lt;li&gt;A simple render function&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;rl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"raylib"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Paddle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@This&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Paddle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Paddle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawRectangleV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might have been nice to be able to have the paddle calculate more of its own
values, but the more I think about it, the more it makes sense to keep the logic
in paddle simpler.&lt;/p&gt;

&lt;h2 id="ball-placeholder"&gt;Ball Placeholder&lt;/h2&gt;

&lt;p&gt;To wrap things up for this session, I added a static ball in the center of the
screen. It has a radius, position, and velocity fields ready to go. Rendering is
straightforward:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;rl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"raylib"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Ball&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@This&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;f32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;vel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Vector2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ball&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawCircleV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2 id="whats-next"&gt;What’s Next&lt;/h2&gt;

&lt;p&gt;This was mostly about warming up, but the next episode will tackle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding velocity to the ball&lt;/li&gt;
&lt;li&gt;Basic collision detection with paddles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll try and think about simplifying paddle logic, especially the awkward
symmetry between left and right.&lt;/p&gt;

&lt;p&gt;You can find the full source code
&lt;a href="https://github.com/drone-ah/wordsonsand/tree/main/games/pong" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;
.&lt;/p&gt;

&lt;p&gt;See you in part 2!&lt;/p&gt;

&lt;h2 id="links"&gt;Links&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
      &lt;a href="https://www.youtube.com/watch?v=ICq2D_na6zc&amp;amp;list=PLX7QRDvlHn4J5uVbmVlkyDaGJ8utKR9K_" rel="noopener noreferrer"&gt;YouTube Video&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/drone-ah/wordsonsand/tree/shri-codes/pong/part-1/games/pong" rel="noopener noreferrer"&gt;Full Source Code (at this point)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Next: &lt;a href="https://drone-ah.com/2025/07/04/building-pong-in-zig-with-raylib-part-2-ball-movement-paddle-collisions/" rel="noopener noreferrer"&gt;Ball Movement &amp;amp; Paddle Collisions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>zig</category>
      <category>raylib</category>
      <category>gamedev</category>
      <category>pong</category>
    </item>
  </channel>
</rss>
