{"article":{"slug":"popcorn-1-0-moving-from-atomvm-to-otp-beam","title":"Popcorn 1.0: Moving from AtomVM to OTP/BEAM","subtitle":null,"summary":"Software Mansion's Kuba Gonet explains Popcorn 1.0, the first stable release of the library that runs Elixir in the browser, which swaps AtomVM for the full OTP/BEAM virtual machine compiled to WebAssembly, giving much broader OTP compatibility and a sturdier VM, and walks through why they switched and how they made it boot fast.","content_type":"announcement","language":"en","canonical_url":"https://swmansion.com/blog/popcorn-1-0-moving-from-atom-vm-to-otp-beam/","author":{"name":"Kuba Gonet","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Software Mansion","url":"https://swmansion.com/","listing_slug":null,"listing":null},"topics":[{"name":"Elixir","slug":"elixir","url":"https://listedarticles.com/topics/elixir"},{"name":"WebAssembly","slug":"webassembly","url":"https://listedarticles.com/topics/webassembly"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":1914,"reading_minutes":8,"published_at":"2026-10-27T00:00:00.000Z","added_at":"2026-10-28T02:12:44.283Z","updated_at":"2026-10-28T02:12:44.283Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/popcorn-1-0-moving-from-atomvm-to-otp-beam","markdown_url":"https://listedarticles.com/articles/popcorn-1-0-moving-from-atomvm-to-otp-beam.md","example":false,"citation":"Kuba Gonet, Software Mansion. \"Popcorn 1.0: Moving from AtomVM to OTP/BEAM.\" 27 Oct 2026. https://swmansion.com/blog/popcorn-1-0-moving-from-atom-vm-to-otp-beam/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://swmansion.com/blog/popcorn-1-0-moving-from-atom-vm-to-otp-beam/"},"body_markdown":"*Kuba Gonet · Software Mansion · October 27, 2026*\n\nPopcorn is a library that lets you run Elixir in the browser. We recently [released Popcorn 1.0](https://github.com/software-mansion/popcorn/releases/tag/v1.0.0), which replaces AtomVM with OTP/BEAM as the underlying VM and marks it as a first stable release.\n\nFor browser applications built with Popcorn, this gives much broader OTP compatibility, makes it much harder to crash or hang Popcorn's VM, and creates a stable foundation for future releases.\n\nI want to take a moment to talk about the whys and hows.\n\n## Why we moved away from AtomVM\n\nPopcorn started as a research project. We wanted to see how far we could take the \"Elixir on the web\" idea, and where it would break down. We took it surprisingly far, considering that the Wasm ecosystem is still developing.\n\nWe decided to run a real VM in the browser. Compared to other approaches (compiling `.beam` files to Wasm or Elixir AST to JS), this has the upside of supporting Elixir semantics closely.\n\nWe used AtomVM as the underlying runtime. It's a small VM aimed at embedded uses, implementing a subset of OTP/BEAM. At the time, it seemed like a perfect fit for browsers, which in some ways resemble embedded targets; the VM itself is small, hackable, and frankly, it was enjoyable to work on its code.  \nWe also didn't think the BEAM could be compiled to Wasm. It's quite a complex project with a long history. It isn't optimized for binary size and browser speed. Additionally, we saw some previous attempts to compile it for browser use, and they didn't look promising.\n\nOver time, we started to feel that fixing compatibility problems with AtomVM consumed a lot of our time.  \nOur main goal was to use unmodified Elixir code. Unfortunately, it wasn't possible on AtomVM, so we maintained a lot of patches to the standard library. We did our best to fix bugs, implement features, and send the patches upstream. That lasted about a year. Maintaining our fork while shipping Popcorn features became more and more difficult.  \nMaking it 100% compatible with BEAM isn't feasible — BEAM itself is a moving target, and the language, bytecode format, and VM semantics aren't specified at all. AtomVM folks have to track it closely while maintaining the trade-offs needed for embedded use (e.g., some standard library modules in AtomVM have an additional error path for out-of-memory errors).  \nIf only we could use OTP/BEAM directly...\n\nAt the end of last year (2025), Mateusz Furga joined the team and experimented with compiling OTP/BEAM to Wasm. At the time, it didn't work, but I felt it was very close.  \nIn January, I asked an LLM to try building on that work, with absolutely no expectations about the result. Over the course of three days, during which I mostly nudged it in the right direction and shot down bad ideas, we got something working.\n\nThe prototype took about ten seconds to start and its assets were large. Still, the VM was stable, and the port didn't require extensive patching of OTP’s C code.\n\nAfter confirming that it could be done, we focused on moving over bits and pieces from the proof of concept. We took it as an opportunity to revisit decisions we had made for the AtomVM implementation —[[1]](#fn-1) the main ones concerned browser isolation and communication with JS (which is an important part of Popcorn).\n\nA month ago, I felt it was close to the point where I'd be happy with it, and I moved the examples and [Elixir Language Tour](https://elixir-language-tour.swmansion.com/) to the new runtime.\n\n## How did it turn out?\n\nInitially, I was skeptical about the size and the speed of the OTP/BEAM port. It turned out that the ten-second boot was an easily resolved issue[[2]](#fn-2), and we could additionally shave off a lot of unnecessary bytes.\n\nAs it stands today, we ship a 730 KB Wasm binary. All assets are Brotli-compressed, and Brotli happens to be a really good compression scheme. Booting the VM takes around 200 ms.\n\nWe also include a build with a cryptographic library and one without. Most applications can work without the library, but if you're using SSL, checking private/public keys, or generating secure hashes, you need crypto support.\n\nFor comparison, AtomVM is around 250 KB compressed, booting in 80 ms.  \nAlong with the VM binary, we need to add around 2.5 MB for standard library files (although they can be tree-shaken, reducing the size by removing unneeded modules).\n\n![popcorn-sizes.png](https://strapi-production-5f3f.up.railway.app/uploads/popcorn_sizes_12b111b5d6.png)\n\nThe difference between BEAM (no crypto) and AtomVM is around 720 KB.\n\n![popcorn-timings-v2.png](https://strapi-production-5f3f.up.railway.app/uploads/popcorn_timings_v2_8f9e911f3a.png)\n\nAtomVM starts 3.2× faster, but OTP executes the measured workloads 3.4×–1,800× faster.\n\nA few things from the graph: BEAM is comparable when running compiled code, although booting is slower (~240 ms vs. 80 ms). For interpreted code, BEAM is much faster—it takes 70 ms to evaluate a module and run its code. AtomVM takes 240 ms.\n\n> Since writing this blog post, I managed to bring BEAM boot time down to ~200 ms, with 140 ms on a warm boot.\n>\n> I wrote more about OTP/BEAM optimizations in [this blog post](https://swmansion.com/blog/popcorn-not-all-bytes-are-equal/). I found one OTP/BEAM bug and one undocumented feature working against us there.\n\nOverall, things just work. BEAM gave us features that were missing from the version of AtomVM we were using (some have since been implemented): bitstrings, regex, full ETS, protocols, things around `system/process_info`, missing NIFs, and much more[[3]](#fn-3).  \nWe've been running [Elixir Language Tour](https://elixir-language-tour.swmansion.com/) and our [landing page](https://popcorn.swmansion.com/) with it for a while. Recently, we also switched Local LiveView to OTP/BEAM.\n\n## The changes\n\nAs mentioned, we changed how Popcorn works quite a bit. Let me show you some highlights.\n\n### Embracing \"let it crash\"\n\nPreviously, we used `iframe`s to isolate VM crashes from the main browser window. They have some quirks you need to be mindful of (such as not being isolated at all when they share an origin with the main window, as we learned).\n\nWe decided to move fully to Web Workers, which are a better fit for this kind of usage. This let us run multiple VM instances, simplified the code for actually running the thing, and isolated the main window from misbehaving VMs.  \nThe BEAM is much more stable than the previous runtime, and the few crashes we observed were connected to our own patches (which we try to keep to a minimum, their implementation has been fixed since).\n\nWe refined our philosophy on handling errors in JS. We fail fast when you misuse the API, throwing exceptions. For expected errors that should be handled, we use `Result`-typed return values. This improves both your experience as a user and our experience when developing Popcorn.\n\n### Packaging\n\nPeople ask me in the letters: \"What about the standard library?\"[[4]](#fn-4) I've got you covered.\n\nFor shipping the standard library to the web, we previously used heavily patched stdlib beams bundled into an `.avm` file. With OTP/BEAM, we took a simpler route: take all apps' `.beam` files, throw 'em into a `.tar`, and compress 'em into a `.tar.br` archive. It works surprisingly well, especially on the compression front.\n\nWe don't have many things to work around, either! Just the usual browser limitations (sockets, DNS, filesystem) and some modules that depend on now-removed NIFs.\n\nOne pretty heavy part of OTP/BEAM is the `crypto` app. To provide it, we need to compile OpenSSL (which BEAM uses for crypto) into the Wasm binary. Unless you need cryptographically random bytes or algorithms (hello, `mix install`), you can use a version without it, which is a tad lighter.\n\n### Making requests\n\nOne problem with running OTP in a browser is that the usual networking stack isn't there. Req, a popular library for making requests, normally uses Finch, which expects TCP sockets, which aren't available in browsers.\n\nWe created the `Popcorn.Fetch` module, which implements a Req adapter backed by the browser's `fetch()` API. We use it as the default adapter in Popcorn, but you still have the option to use your own adapter if you want to.\n\nWhile `fetch()` has some limitations related to CORS, redirects, and which headers can be set, you can now use Req for your requests **without reaching for JS APIs.**\n\n### New API\n\nFor a long time, Popcorn had `call()` and `cast()` which pretended to do the thing they were named after but really just sent a plain message to the process.  \nThis was awkward — you needed to use `handle_info/2` and transform the message before you could handle it.  \nWe now use a version of it that actually forwards them to `handle_call` and `handle_cast` and things work just as you might expect.\n\nThe plain `send()` function was finally added as well. In JS, its signature is:\n\n```\nasync send(rawTarget: string | Pid, payload: AnyValue): Promise<void>\n```\n\nThis means that you can pass a named process or \"PID handle\" obtained from Elixir (via `JS.run()` return value) and send an arbitrary payload. The function returns a Promise that resolves after a message is put in the target process's mailbox.  \nIt has slightly different behavior from OTP/BEAM `send()` (which ignores invalid PIDs) but it's a better fit for JS.\n\nWhen redesigning the API, we focused on creating a fairly simple API surface that guides you toward success[[5]](#fn-5) and requires minimal configuration. I encourage you to read the [docs](https://popcorn.hexdocs.pm/0.4.0/readme.html) to learn more.\n\n## Upgrading\n\nThe entire process for migrating from older versions of Popcorn is described in the [documentation](https://popcorn.hexdocs.pm/1.0.0/0-3-migration.html) and release notes. Things work pretty much the same, and all breaking changes are pretty mechanical (for example, [this PR migrates Elixir Language Tour to OTP/BEAM](https://github.com/software-mansion/popcorn/pull/733/changes/c6c7e121cb61b3638c834b22f1305f40afcdeec7#diff-0501c8007998e970456ff697cbbb62e606d77e8a1d304ba3e602f8fdab106c8fL22-L62)).\n\nI also put some work to write guides for newcomers, both ones that are more familiar with Elixir and ones that prefer JavaScript.\n\n## What's left?\n\nOne project we have in the works is PopDoc (an ExDoc plugin for interactive docs), and we plan to improve Local LiveView and treeshaking a little bit.\n\nFor Popcorn itself, we just need some finishing touches — examples, and optimizations for size and speed. The API is quite stable. I'd personally like to see some APIs built on top of `Popcorn.JS.run/3`, making it easier to interact with JS code (e.g. libraries) but keeping it in Elixir code.\n\nI know few people waited for Popcorn that's compatible with newer versions of the BEAM. For previous version this was very hard. Now, updates for us should be simpler and you can expect support for new BEAM versions coming much faster.\n\n## Closing thoughts\n\nSo far, this has been a really cool project to work on, and I'm grateful to Software Mansion for sponsoring the work and to everyone on the team, past and present.\n\nPlease give it a try. If you have any ideas, feedback, or cool demos, share them with me — I'm always happy to see Popcorn in use.\n\nUntil next time!\n\n---\n\n1. My em-dashes are generated in a controlled, organic environment. They live a happy life there, actually.[↩︎](#fnref-1)\n2. After benchmarking, we discovered that we spent a lot of time during boot waiting for stdin input. `stdin` was implemented using `Atomics` in Popcorn and got a good night's sleep for 10 ms with every read. Fine for a few `stdin` reads, not so much for 1 300 reads.[↩︎](#fnref-2)\n3. Here's [the full list of patches](https://github.com/software-mansion/popcorn/tree/7d4f24f56b8efcf0d3322dfe112a1179e6032b4b/popcorn-2/elixir/patches).[↩︎](#fnref-3)\n4. Both \"People\" and \"asking in letters\" may or may not be pure fiction. I'd love to receive a handwritten letter one of these days![↩︎](#fnref-4)\n5. <https://blog.codinghorror.com/falling-into-the-pit-of-success/>[↩︎](#fnref-5)\n\n---\n\n*Originally published at [Software Mansion](https://swmansion.com/blog/popcorn-1-0-moving-from-atom-vm-to-otp-beam/).*\n","body_html":"<p><em>Kuba Gonet · Software Mansion · October 27, 2026</em></p>\n<p>Popcorn is a library that lets you run Elixir in the browser. We recently <a href=\"https://github.com/software-mansion/popcorn/releases/tag/v1.0.0\" rel=\"nofollow ugc noopener\">released Popcorn 1.0</a>, which replaces AtomVM with OTP/BEAM as the underlying VM and marks it as a first stable release.</p>\n<p>For browser applications built with Popcorn, this gives much broader OTP compatibility, makes it much harder to crash or hang Popcorn&#39;s VM, and creates a stable foundation for future releases.</p>\n<p>I want to take a moment to talk about the whys and hows.</p>\n<h2 id=\"why-we-moved-away-from-atomvm\">Why we moved away from AtomVM</h2>\n<p>Popcorn started as a research project. We wanted to see how far we could take the &quot;Elixir on the web&quot; idea, and where it would break down. We took it surprisingly far, considering that the Wasm ecosystem is still developing.</p>\n<p>We decided to run a real VM in the browser. Compared to other approaches (compiling <code>.beam</code> files to Wasm or Elixir AST to JS), this has the upside of supporting Elixir semantics closely.</p>\n<p>We used AtomVM as the underlying runtime. It&#39;s a small VM aimed at embedded uses, implementing a subset of OTP/BEAM. At the time, it seemed like a perfect fit for browsers, which in some ways resemble embedded targets; the VM itself is small, hackable, and frankly, it was enjoyable to work on its code.<br />\nWe also didn&#39;t think the BEAM could be compiled to Wasm. It&#39;s quite a complex project with a long history. It isn&#39;t optimized for binary size and browser speed. Additionally, we saw some previous attempts to compile it for browser use, and they didn&#39;t look promising.</p>\n<p>Over time, we started to feel that fixing compatibility problems with AtomVM consumed a lot of our time.<br />\nOur main goal was to use unmodified Elixir code. Unfortunately, it wasn&#39;t possible on AtomVM, so we maintained a lot of patches to the standard library. We did our best to fix bugs, implement features, and send the patches upstream. That lasted about a year. Maintaining our fork while shipping Popcorn features became more and more difficult.<br />\nMaking it 100% compatible with BEAM isn&#39;t feasible — BEAM itself is a moving target, and the language, bytecode format, and VM semantics aren&#39;t specified at all. AtomVM folks have to track it closely while maintaining the trade-offs needed for embedded use (e.g., some standard library modules in AtomVM have an additional error path for out-of-memory errors).<br />\nIf only we could use OTP/BEAM directly...</p>\n<p>At the end of last year (2025), Mateusz Furga joined the team and experimented with compiling OTP/BEAM to Wasm. At the time, it didn&#39;t work, but I felt it was very close.<br />\nIn January, I asked an LLM to try building on that work, with absolutely no expectations about the result. Over the course of three days, during which I mostly nudged it in the right direction and shot down bad ideas, we got something working.</p>\n<p>The prototype took about ten seconds to start and its assets were large. Still, the VM was stable, and the port didn&#39;t require extensive patching of OTP’s C code.</p>\n<p>After confirming that it could be done, we focused on moving over bits and pieces from the proof of concept. We took it as an opportunity to revisit decisions we had made for the AtomVM implementation —<a href=\"#fn-1\">[1]</a> the main ones concerned browser isolation and communication with JS (which is an important part of Popcorn).</p>\n<p>A month ago, I felt it was close to the point where I&#39;d be happy with it, and I moved the examples and <a href=\"https://elixir-language-tour.swmansion.com/\" rel=\"nofollow ugc noopener\">Elixir Language Tour</a> to the new runtime.</p>\n<h2 id=\"how-did-it-turn-out\">How did it turn out?</h2>\n<p>Initially, I was skeptical about the size and the speed of the OTP/BEAM port. It turned out that the ten-second boot was an easily resolved issue<a href=\"#fn-2\">[2]</a>, and we could additionally shave off a lot of unnecessary bytes.</p>\n<p>As it stands today, we ship a 730 KB Wasm binary. All assets are Brotli-compressed, and Brotli happens to be a really good compression scheme. Booting the VM takes around 200 ms.</p>\n<p>We also include a build with a cryptographic library and one without. Most applications can work without the library, but if you&#39;re using SSL, checking private/public keys, or generating secure hashes, you need crypto support.</p>\n<p>For comparison, AtomVM is around 250 KB compressed, booting in 80 ms.<br />\nAlong with the VM binary, we need to add around 2.5 MB for standard library files (although they can be tree-shaken, reducing the size by removing unneeded modules).</p>\n<figure><img src=\"https://strapi-production-5f3f.up.railway.app/uploads/popcorn_sizes_12b111b5d6.png\" alt=\"popcorn-sizes.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>The difference between BEAM (no crypto) and AtomVM is around 720 KB.</p>\n<figure><img src=\"https://strapi-production-5f3f.up.railway.app/uploads/popcorn_timings_v2_8f9e911f3a.png\" alt=\"popcorn-timings-v2.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>AtomVM starts 3.2× faster, but OTP executes the measured workloads 3.4×–1,800× faster.</p>\n<p>A few things from the graph: BEAM is comparable when running compiled code, although booting is slower (~240 ms vs. 80 ms). For interpreted code, BEAM is much faster—it takes 70 ms to evaluate a module and run its code. AtomVM takes 240 ms.</p>\n<blockquote><p>Since writing this blog post, I managed to bring BEAM boot time down to ~200 ms, with 140 ms on a warm boot.</p>\n<p>I wrote more about OTP/BEAM optimizations in <a href=\"https://swmansion.com/blog/popcorn-not-all-bytes-are-equal/\" rel=\"nofollow ugc noopener\">this blog post</a>. I found one OTP/BEAM bug and one undocumented feature working against us there.</p></blockquote>\n<p>Overall, things just work. BEAM gave us features that were missing from the version of AtomVM we were using (some have since been implemented): bitstrings, regex, full ETS, protocols, things around <code>system/process_info</code>, missing NIFs, and much more<a href=\"#fn-3\">[3]</a>.<br />\nWe&#39;ve been running <a href=\"https://elixir-language-tour.swmansion.com/\" rel=\"nofollow ugc noopener\">Elixir Language Tour</a> and our <a href=\"https://popcorn.swmansion.com/\" rel=\"nofollow ugc noopener\">landing page</a> with it for a while. Recently, we also switched Local LiveView to OTP/BEAM.</p>\n<h2 id=\"the-changes\">The changes</h2>\n<p>As mentioned, we changed how Popcorn works quite a bit. Let me show you some highlights.</p>\n<h3 id=\"embracing-let-it-crash\">Embracing &quot;let it crash&quot;</h3>\n<p>Previously, we used <code>iframe</code>s to isolate VM crashes from the main browser window. They have some quirks you need to be mindful of (such as not being isolated at all when they share an origin with the main window, as we learned).</p>\n<p>We decided to move fully to Web Workers, which are a better fit for this kind of usage. This let us run multiple VM instances, simplified the code for actually running the thing, and isolated the main window from misbehaving VMs.<br />\nThe BEAM is much more stable than the previous runtime, and the few crashes we observed were connected to our own patches (which we try to keep to a minimum, their implementation has been fixed since).</p>\n<p>We refined our philosophy on handling errors in JS. We fail fast when you misuse the API, throwing exceptions. For expected errors that should be handled, we use <code>Result</code>-typed return values. This improves both your experience as a user and our experience when developing Popcorn.</p>\n<h3 id=\"packaging\">Packaging</h3>\n<p>People ask me in the letters: &quot;What about the standard library?&quot;<a href=\"#fn-4\">[4]</a> I&#39;ve got you covered.</p>\n<p>For shipping the standard library to the web, we previously used heavily patched stdlib beams bundled into an <code>.avm</code> file. With OTP/BEAM, we took a simpler route: take all apps&#39; <code>.beam</code> files, throw &#39;em into a <code>.tar</code>, and compress &#39;em into a <code>.tar.br</code> archive. It works surprisingly well, especially on the compression front.</p>\n<p>We don&#39;t have many things to work around, either! Just the usual browser limitations (sockets, DNS, filesystem) and some modules that depend on now-removed NIFs.</p>\n<p>One pretty heavy part of OTP/BEAM is the <code>crypto</code> app. To provide it, we need to compile OpenSSL (which BEAM uses for crypto) into the Wasm binary. Unless you need cryptographically random bytes or algorithms (hello, <code>mix install</code>), you can use a version without it, which is a tad lighter.</p>\n<h3 id=\"making-requests\">Making requests</h3>\n<p>One problem with running OTP in a browser is that the usual networking stack isn&#39;t there. Req, a popular library for making requests, normally uses Finch, which expects TCP sockets, which aren&#39;t available in browsers.</p>\n<p>We created the <code>Popcorn.Fetch</code> module, which implements a Req adapter backed by the browser&#39;s <code>fetch()</code> API. We use it as the default adapter in Popcorn, but you still have the option to use your own adapter if you want to.</p>\n<p>While <code>fetch()</code> has some limitations related to CORS, redirects, and which headers can be set, you can now use Req for your requests <strong>without reaching for JS APIs.</strong></p>\n<h3 id=\"new-api\">New API</h3>\n<p>For a long time, Popcorn had <code>call()</code> and <code>cast()</code> which pretended to do the thing they were named after but really just sent a plain message to the process.<br />\nThis was awkward — you needed to use <code>handle_info/2</code> and transform the message before you could handle it.<br />\nWe now use a version of it that actually forwards them to <code>handle_call</code> and <code>handle_cast</code> and things work just as you might expect.</p>\n<p>The plain <code>send()</code> function was finally added as well. In JS, its signature is:</p>\n<pre><code>async send(rawTarget: string | Pid, payload: AnyValue): Promise&lt;void&gt;</code></pre>\n<p>This means that you can pass a named process or &quot;PID handle&quot; obtained from Elixir (via <code>JS.run()</code> return value) and send an arbitrary payload. The function returns a Promise that resolves after a message is put in the target process&#39;s mailbox.<br />\nIt has slightly different behavior from OTP/BEAM <code>send()</code> (which ignores invalid PIDs) but it&#39;s a better fit for JS.</p>\n<p>When redesigning the API, we focused on creating a fairly simple API surface that guides you toward success<a href=\"#fn-5\">[5]</a> and requires minimal configuration. I encourage you to read the <a href=\"https://popcorn.hexdocs.pm/0.4.0/readme.html\" rel=\"nofollow ugc noopener\">docs</a> to learn more.</p>\n<h2 id=\"upgrading\">Upgrading</h2>\n<p>The entire process for migrating from older versions of Popcorn is described in the <a href=\"https://popcorn.hexdocs.pm/1.0.0/0-3-migration.html\" rel=\"nofollow ugc noopener\">documentation</a> and release notes. Things work pretty much the same, and all breaking changes are pretty mechanical (for example, <a href=\"https://github.com/software-mansion/popcorn/pull/733/changes/c6c7e121cb61b3638c834b22f1305f40afcdeec7#diff-0501c8007998e970456ff697cbbb62e606d77e8a1d304ba3e602f8fdab106c8fL22-L62\" rel=\"nofollow ugc noopener\">this PR migrates Elixir Language Tour to OTP/BEAM</a>).</p>\n<p>I also put some work to write guides for newcomers, both ones that are more familiar with Elixir and ones that prefer JavaScript.</p>\n<h2 id=\"what-s-left\">What&#39;s left?</h2>\n<p>One project we have in the works is PopDoc (an ExDoc plugin for interactive docs), and we plan to improve Local LiveView and treeshaking a little bit.</p>\n<p>For Popcorn itself, we just need some finishing touches — examples, and optimizations for size and speed. The API is quite stable. I&#39;d personally like to see some APIs built on top of <code>Popcorn.JS.run/3</code>, making it easier to interact with JS code (e.g. libraries) but keeping it in Elixir code.</p>\n<p>I know few people waited for Popcorn that&#39;s compatible with newer versions of the BEAM. For previous version this was very hard. Now, updates for us should be simpler and you can expect support for new BEAM versions coming much faster.</p>\n<h2 id=\"closing-thoughts\">Closing thoughts</h2>\n<p>So far, this has been a really cool project to work on, and I&#39;m grateful to Software Mansion for sponsoring the work and to everyone on the team, past and present.</p>\n<p>Please give it a try. If you have any ideas, feedback, or cool demos, share them with me — I&#39;m always happy to see Popcorn in use.</p>\n<p>Until next time!</p>\n<hr />\n<ol><li>My em-dashes are generated in a controlled, organic environment. They live a happy life there, actually.<a href=\"#fnref-1\">↩︎</a></li><li>After benchmarking, we discovered that we spent a lot of time during boot waiting for stdin input. <code>stdin</code> was implemented using <code>Atomics</code> in Popcorn and got a good night&#39;s sleep for 10 ms with every read. Fine for a few <code>stdin</code> reads, not so much for 1 300 reads.<a href=\"#fnref-2\">↩︎</a></li><li>Here&#39;s <a href=\"https://github.com/software-mansion/popcorn/tree/7d4f24f56b8efcf0d3322dfe112a1179e6032b4b/popcorn-2/elixir/patches\" rel=\"nofollow ugc noopener\">the full list of patches</a>.<a href=\"#fnref-3\">↩︎</a></li><li>Both &quot;People&quot; and &quot;asking in letters&quot; may or may not be pure fiction. I&#39;d love to receive a handwritten letter one of these days↩︎</li><li><a href=\"https://blog.codinghorror.com/falling-into-the-pit-of-success/\" rel=\"nofollow ugc noopener\">https://blog.codinghorror.com/falling-into-the-pit-of-success/</a><a href=\"#fnref-5\">↩︎</a></li></ol>\n<hr />\n<p><em>Originally published at <a href=\"https://swmansion.com/blog/popcorn-1-0-moving-from-atom-vm-to-otp-beam/\" rel=\"nofollow ugc noopener\">Software Mansion</a>.</em></p>","headings":[{"level":2,"text":"Why we moved away from AtomVM","id":"why-we-moved-away-from-atomvm"},{"level":2,"text":"How did it turn out?","id":"how-did-it-turn-out"},{"level":2,"text":"The changes","id":"the-changes"},{"level":3,"text":"Embracing \"let it crash\"","id":"embracing-let-it-crash"},{"level":3,"text":"Packaging","id":"packaging"},{"level":3,"text":"Making requests","id":"making-requests"},{"level":3,"text":"New API","id":"new-api"},{"level":2,"text":"Upgrading","id":"upgrading"},{"level":2,"text":"What's left?","id":"what-s-left"},{"level":2,"text":"Closing thoughts","id":"closing-thoughts"}]}}