diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 000000000..2451c27ca
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+3.0.7
diff --git a/Gemfile b/Gemfile
index b3b1956fc..f24d05f4a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,5 +2,7 @@ source 'https://rubygems.org'
 
 gem 'github-pages'
 gem 'json', '>= 2.0.0'
-
-gem "webrick", "~> 1.8"
+gem 'webrick', '>= 1.8'
+gem 'csv', '~> 3.3'
+gem 'base64', '~> 0.2.0'
+gem 'bigdecimal', '~> 3.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index 8677d4264..bb36d1087 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -8,6 +8,8 @@ GEM
       tzinfo (~> 2.0)
     addressable (2.8.1)
       public_suffix (>= 2.0.2, < 6.0)
+    base64 (0.2.0)
+    bigdecimal (3.1.9)
     coffee-script (2.4.1)
       coffee-script-source
       execjs
@@ -15,6 +17,7 @@ GEM
     colorator (1.1.0)
     commonmarker (0.23.10)
     concurrent-ruby (1.2.2)
+    csv (3.3.3)
     dnsruby (1.61.9)
       simpleidn (~> 0.1)
     em-websocket (0.5.3)
@@ -225,8 +228,7 @@ GEM
     rb-fsevent (0.11.2)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
-    rexml (3.3.6)
-      strscan
+    rexml (3.3.9)
     rouge (3.26.0)
     ruby2_keywords (0.0.5)
     rubyzip (2.3.2)
@@ -241,7 +243,6 @@ GEM
       faraday (>= 0.17.3, < 3)
     simpleidn (0.2.1)
       unf (~> 0.1.4)
-    strscan (3.1.0)
     terminal-table (1.8.0)
       unicode-display_width (~> 1.1, >= 1.1.1)
     typhoeus (1.4.0)
@@ -252,15 +253,18 @@ GEM
       unf_ext
     unf_ext (0.0.8.2)
     unicode-display_width (1.8.0)
-    webrick (1.8.1)
+    webrick (1.8.2)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
+  base64 (~> 0.2.0)
+  bigdecimal (~> 3.1)
+  csv (~> 3.3)
   github-pages
   json (>= 2.0.0)
-  webrick (~> 1.8)
+  webrick (>= 1.8)
 
 BUNDLED WITH
-   2.3.7
+   2.5.23
diff --git a/_data/elixir-versions.yml b/_data/elixir-versions.yml
index 93d640300..4d2593c70 100644
--- a/_data/elixir-versions.yml
+++ b/_data/elixir-versions.yml
@@ -1,8 +1,16 @@
-stable: v1_17
+stable: v1_18
+
+v1_18:
+  name: v1.18
+  minimum_otp: 26.0
+  recommended_otp: 27.3.4
+  otp_versions: [27, 26, 25]
+  version: 1.18.4
 
 v1_17:
   name: v1.17
   minimum_otp: 25.0
+  recommended_otp: 27.1.2
   otp_versions: [27, 26, 25]
   version: 1.17.3
 
diff --git a/_includes/events.html b/_includes/events.html
index 6a9edc1f3..7aedcfb1f 100644
--- a/_includes/events.html
+++ b/_includes/events.html
@@ -1,14 +1,11 @@
 <div class="widget events">
   <h3 class="widget-title">Upcoming events</h3>
-  <a href="https://elixir-webrtc.org/elixir-stream-week">
-    <span
-      style="font-size: 22px; font-weight: bold; line-height: 110%; background: linear-gradient(261.82deg, #46ADD8 -4.89%, #675AF1 82.73%); color: transparent; background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
-      Elixir Stream Week
-    </span>
+  <a href="https://elixirconf.com/">
+    <img src="https://2022.elixirconf.com/images/resources/elixirconf-logo.svg" alt="ElixirConf" />
     <br />
     <ul>
-      <li><b>Oct 21-25, 2024</b> - Remote</li>
-      <li><b>5 days, 5 streams, 5 Elixir experts</b></li>
+      <li><b>Aug 28-29, 2025</b> - Orlando, FL.</li>
+      <li><b>Aug 27 - Seven Workshops to choose from</b></li>
     </ul>
   </a>
 </div>
\ No newline at end of file
diff --git a/_includes/important-links.html b/_includes/important-links.html
index 5cf0c3259..c4d5c0702 100644
--- a/_includes/important-links.html
+++ b/_includes/important-links.html
@@ -1,13 +1,19 @@
 <div class="widget">
   <h3 class="widget-title">Important links</h3>
   <ul>
-    <li class="menu-item development"><a class="spec" href="/development.html">Development & Team</a></li>
-    <li><a class="spec" href="https://github.com/elixir-lang/elixir">Source code & issues tracker</a></li>
+    <li class="menu-item development">
+      <a class="spec" href="/development.html">Development & Team</a>
+    </li>
+    <li>
+      <a class="spec" href="https://github.com/elixir-lang/elixir"
+        >Source code & issues tracker</a
+      >
+    </li>
   </ul>
 </div>
 
 <div id="mini-docu" class="widget">
-  <a href="https://cult.honeypot.io/originals/elixir-the-documentary">
+  <a href="https://www.youtube.com/watch?v=lxYFOM3UJzo">
     <div class="mini-docu-cta">
       <div class="mini-docu-copy">Watch the Elixir<br />mini-documentary!</div>
     </div>
@@ -25,16 +31,33 @@ <h3 class="widget-title">Join the Community</h3>
     <li><a class="spec" href="http://elixirforum.com">Elixir Forum</a></li>
     <li><a class="spec" href="https://elixir-slack.community">Elixir on Slack</a></li>
     <li><a class="spec" href="https://discord.gg/elixir">Elixir on Discord</a></li>
-    <li><a class="spec" href="https://github.com/elixir-lang/elixir/wiki/Code-Editor-Support">IDE/Editor support</a>
+    <li>
+      <a class="spec" href="https://github.com/elixir-lang/elixir/wiki/Code-Editor-Support"
+        >IDE/Editor support</a
+      >
+    </li>
+    <li>
+      <a class="spec" href="https://www.meetup.com/topics/elixir/">Meetups around the world</a>
+    </li>
+    <li>
+      <a class="spec" href="https://github.com/elixir-lang/elixir/wiki/Hiring-Elixir-Developers"
+        >Jobs and hiring (community wiki)</a
+      >
+    </li>
+    <li>
+      <a class="spec" href="https://github.com/elixir-lang/elixir/wiki"
+        >Events and resources (community wiki)</a
+      >
     </li>
-    <li><a class="spec" href="https://www.meetup.com/topics/elixir/">Meetups around the world</a></li>
-    <li><a class="spec" href="https://github.com/elixir-lang/elixir/wiki/Hiring-Elixir-Developers">Jobs and hiring
-        (community wiki)</a></li>
-    <li><a class="spec" href="https://github.com/elixir-lang/elixir/wiki">Events and resources (community wiki)</a></li>
   </ul>
 </div>
 
 <div id="eef" class="widget">
-  <a href="https://erlef.org/" title="Join the Erlang Ecosystem Foundation"><img src="/images/logo/eef.png"
-      alt="Join the Erlang Ecosystem Foundation" width="174" style="margin-top:-10px" /></a>
-</div>
\ No newline at end of file
+  <a href="https://erlef.org/" title="Join the Erlang Ecosystem Foundation"
+    ><img
+      src="/images/logo/eef.png"
+      alt="Join the Erlang Ecosystem Foundation"
+      width="174"
+      style="margin-top: -10px"
+  /></a>
+</div>
diff --git a/_includes/search.html b/_includes/search.html
index 651220219..8535bb553 100644
--- a/_includes/search.html
+++ b/_includes/search.html
@@ -1,5 +1,5 @@
 <div class="widget news">
-  <h3>News: <a href="/blog/2024/06/12/elixir-v1-17-0-released/">Elixir v1.17 released</a></h3>
+  <h3>News: <a href="/blog/2024/12/19/elixir-v1-18-0-released/">Elixir v1.18 released</a></h3>
 </div>
 
 <div class="widget search">
diff --git a/_layouts/post.html b/_layouts/post.html
index 8cde0eff9..4cab9e33a 100644
--- a/_layouts/post.html
+++ b/_layouts/post.html
@@ -11,7 +11,7 @@ <h1>{{ page.title }}</h1>
         {% if page.subtitle %}
         <h2>{{ page.subtitle }}</h2>
         {% endif %}
-        <div class="byline">{{ page.date | date: "%B %d, %Y" }}{% if page.author %} &middot; by {{ page.author}}{% endif %} &middot; in {% for category in page.categories %}
+        <div class="byline">{{ page.date | date: "%B %d, %Y" }}{% if page.authors %} &middot; by {{ page.authors | join: ", " }}{% endif %} &middot; in {% for category in page.categories %}
           {% if category == "Elixir in Production" %}
             <a class="category" href="/cases.html">{{ category }}</a>
           {% else %}
diff --git a/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown b/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown
index e4f0fe17f..591610198 100644
--- a/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown
+++ b/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: A peek inside Elixir's Parallel Compiler
-author: José Valim
+authors:
+-  José Valim
 category: Internals
 excerpt: Today, a parallel compiler just landed in Elixir main. The goal of the parallel compiler is to compile files in parallel, automatically detecting dependencies between files. In this blog post, we are going to take a peek into the parallel compiler internals and learn more about Erlang and Elixir in the process.
 ---
diff --git a/_posts/2012-05-25-elixir-v0-5-0-released.markdown b/_posts/2012-05-25-elixir-v0-5-0-released.markdown
index cc7fa3fa6..a5701a60d 100644
--- a/_posts/2012-05-25-elixir-v0-5-0-released.markdown
+++ b/_posts/2012-05-25-elixir-v0-5-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.5.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: We have finally released Elixir v0.5.0! This marks the first release since the language was rewritten. In this blog post, we will discuss what we achieved during this time and what are the next steps!
 
diff --git a/_posts/2012-08-01-elixir-v0-6-0-released.markdown b/_posts/2012-08-01-elixir-v0-6-0-released.markdown
index 355c4d991..becafdf7c 100644
--- a/_posts/2012-08-01-elixir-v0-6-0-released.markdown
+++ b/_posts/2012-08-01-elixir-v0-6-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.6.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: We have finally released Elixir v0.6.0! This release includes a build tool called Mix, support for Erlang typespecs, many improvements to IEx and improved IO, File and Macro support.
 
diff --git a/_posts/2012-10-20-elixir-v0-7-0-released.markdown b/_posts/2012-10-20-elixir-v0-7-0-released.markdown
index 2d41eb167..d2f181612 100644
--- a/_posts/2012-10-20-elixir-v0-7-0-released.markdown
+++ b/_posts/2012-10-20-elixir-v0-7-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.7.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.7.0 is released with many improvements! Read on for more information.
 
diff --git a/_posts/2012-11-18-elixir-v0-7-1-released.markdown b/_posts/2012-11-18-elixir-v0-7-1-released.markdown
index 7a1ff19a0..113bcd31f 100644
--- a/_posts/2012-11-18-elixir-v0-7-1-released.markdown
+++ b/_posts/2012-11-18-elixir-v0-7-1-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.7.1 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.7.1 was released to celebrate the end of a two months journey traveling around Europe, United States and Brazil talking about Elixir.
 
diff --git a/_posts/2012-12-04-elixir-v0-7-2-released.markdown b/_posts/2012-12-04-elixir-v0-7-2-released.markdown
index c18b6ccb4..b4ec972c7 100644
--- a/_posts/2012-12-04-elixir-v0-7-2-released.markdown
+++ b/_posts/2012-12-04-elixir-v0-7-2-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.7.2 released
-author: Yurii Rashkovskii
+authors:
+-  Yurii Rashkovskii
 category: Releases
 excerpt: Elixir v0.7.2 is released, new, improved type specifications syntax and many other improvements.
 
diff --git a/_posts/2013-01-27-elixir-v0-8-0-released.markdown b/_posts/2013-01-27-elixir-v0-8-0-released.markdown
index 2a07d42ec..9f6236b10 100644
--- a/_posts/2013-01-27-elixir-v0-8-0-released.markdown
+++ b/_posts/2013-01-27-elixir-v0-8-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.8.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: On the last 9th January, we celebrated two years since Elixir's first commit and to celebrate this occasion we have prepared a big release. Elixir v0.8 is out, with documentation, optimizations, bug fixes and shiny new features. Let's take a look at them!
 ---
diff --git a/_posts/2013-04-19-google-summer-of-code-2013.markdown b/_posts/2013-04-19-google-summer-of-code-2013.markdown
index b025579f6..d964d7c1b 100644
--- a/_posts/2013-04-19-google-summer-of-code-2013.markdown
+++ b/_posts/2013-04-19-google-summer-of-code-2013.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Google Summer of Code 2013
-author: José Valim
+authors:
+-  José Valim
 category: Announcements
 excerpt: Elixir is taking part in Google Summer of Code 2013! Are you a student? Join us!
 ---
diff --git a/_posts/2013-04-29-elixir-v0-8-2-released.markdown b/_posts/2013-04-29-elixir-v0-8-2-released.markdown
index 18f1b2ea9..fea64d566 100644
--- a/_posts/2013-04-29-elixir-v0-8-2-released.markdown
+++ b/_posts/2013-04-29-elixir-v0-8-2-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.8.2 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.8.2 is released with bug fixes, better Erlang R16 support and doctests.
 ---
diff --git a/_posts/2013-05-02-elixir-on-xen.markdown b/_posts/2013-05-02-elixir-on-xen.markdown
index a4dd2de42..9f1de4c2b 100644
--- a/_posts/2013-05-02-elixir-on-xen.markdown
+++ b/_posts/2013-05-02-elixir-on-xen.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir on Xen
-author: José Valim
+authors:
+-  José Valim
 category: Announcements
 excerpt: The Erlang on Xen team has added support for Elixir and we will tell you how you can use it!
 ---
diff --git a/_posts/2013-05-23-elixir-v0-9-0-released.markdown b/_posts/2013-05-23-elixir-v0-9-0-released.markdown
index 289dae2dd..edee304e1 100644
--- a/_posts/2013-05-23-elixir-v0-9-0-released.markdown
+++ b/_posts/2013-05-23-elixir-v0-9-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.9.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.9.0 is released with support for reducers, umbrella projects, faster compilation times and dropped support for R15 and earlier OTP versions.
 ---
diff --git a/_posts/2013-07-13-elixir-v0-10-0-released.markdown b/_posts/2013-07-13-elixir-v0-10-0-released.markdown
index d67b366b8..c00858ea8 100644
--- a/_posts/2013-07-13-elixir-v0-10-0-released.markdown
+++ b/_posts/2013-07-13-elixir-v0-10-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.10.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.10.0 is out with support for streams, sets, pretty printing and many improvements for Mix and ExUnit.
 ---
diff --git a/_posts/2013-08-08-elixir-design-goals.markdown b/_posts/2013-08-08-elixir-design-goals.markdown
index 7509cc0d3..5959dab92 100644
--- a/_posts/2013-08-08-elixir-design-goals.markdown
+++ b/_posts/2013-08-08-elixir-design-goals.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir Design Goals
-author: José Valim
+authors:
+-  José Valim
 category: Internals
 excerpt: Highlight of Elixir design goals.
 ---
diff --git a/_posts/2013-11-05-elixir-v0-11-0-released.markdown b/_posts/2013-11-05-elixir-v0-11-0-released.markdown
index f8dbc43b6..1a668262c 100644
--- a/_posts/2013-11-05-elixir-v0-11-0-released.markdown
+++ b/_posts/2013-11-05-elixir-v0-11-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.11.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.11.0 is out and it focus on improving and optimizing the patterns often used by the community.
 ---
diff --git a/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown b/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown
index 9a0670d9f..b29807cb4 100644
--- a/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown
+++ b/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir's new continuable enumerators
-author: Peter Minten
+authors:
+-  Peter Minten
 category: Internals
 excerpt: In 0.12.0 Elixir's enumerators have gained the ability to suspend value
          production and to terminate early.
diff --git a/_posts/2013-12-15-elixir-v0-12-0-released.markdown b/_posts/2013-12-15-elixir-v0-12-0-released.markdown
index 562f65467..fe8a349e3 100644
--- a/_posts/2013-12-15-elixir-v0-12-0-released.markdown
+++ b/_posts/2013-12-15-elixir-v0-12-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.12.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v0.12.0 is out with improved enumerables, build patterns and welcoming a new member to our team
 ---
diff --git a/_posts/2014-04-21-elixir-v0-13-0-released.markdown b/_posts/2014-04-21-elixir-v0-13-0-released.markdown
index eb1532441..995e4d68c 100644
--- a/_posts/2014-04-21-elixir-v0-13-0-released.markdown
+++ b/_posts/2014-04-21-elixir-v0-13-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.13.0 released, hex.pm and ElixirConf announced
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: "Elixir v0.13.0 comes with substantial improvements to the language: maps, structs, comprehensiona and more. It also marks the announcement of the hex.pm package manager and the announcement of ElixirConf!"
 ---
diff --git a/_posts/2014-06-17-elixir-v0-14-0-released.markdown b/_posts/2014-06-17-elixir-v0-14-0-released.markdown
index 0cd089535..cfa23e5ca 100644
--- a/_posts/2014-06-17-elixir-v0-14-0-released.markdown
+++ b/_posts/2014-06-17-elixir-v0-14-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.14.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: "Elixir v0.14.0 is released and expands the work on structs and bringing more of OTP right into Elixir and Mix"
 ---
diff --git a/_posts/2014-08-07-elixir-v0-15-0-released.markdown b/_posts/2014-08-07-elixir-v0-15-0-released.markdown
index e99cebaab..32b579555 100644
--- a/_posts/2014-08-07-elixir-v0-15-0-released.markdown
+++ b/_posts/2014-08-07-elixir-v0-15-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v0.15.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: "Elixir v0.15.0 introduces Elixir's Logger, Mix aliases and is the last stop before Elixir v1.0. We are also glad to welcome Alexei into our team!"
 ---
diff --git a/_posts/2014-09-18-elixir-v1-0-0-released.markdown b/_posts/2014-09-18-elixir-v1-0-0-released.markdown
index 5e07033dd..72929864c 100644
--- a/_posts/2014-09-18-elixir-v1-0-0-released.markdown
+++ b/_posts/2014-09-18-elixir-v1-0-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.0 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.0 is finally out!
 ---
diff --git a/_posts/2015-09-28-elixir-v1-1-0-released.markdown b/_posts/2015-09-28-elixir-v1-1-0-released.markdown
index e5f85c7a5..5adecea87 100644
--- a/_posts/2015-09-28-elixir-v1-1-0-released.markdown
+++ b/_posts/2015-09-28-elixir-v1-1-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.1 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.1 brings enhancements, bug fixes, performance improvements and more into Elixir.
 ---
diff --git a/_posts/2016-01-03-elixir-v1-2-0-released.markdown b/_posts/2016-01-03-elixir-v1-2-0-released.markdown
index beb51fe8b..1b8a7efd8 100644
--- a/_posts/2016-01-03-elixir-v1-2-0-released.markdown
+++ b/_posts/2016-01-03-elixir-v1-2-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.2 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.2 brings enhancements, bug fixes, performance improvements and more into Elixir.
 ---
diff --git a/_posts/2016-06-21-elixir-v1-3-0-released.markdown b/_posts/2016-06-21-elixir-v1-3-0-released.markdown
index 13ade0b0b..3ee45d0e0 100644
--- a/_posts/2016-06-21-elixir-v1-3-0-released.markdown
+++ b/_posts/2016-06-21-elixir-v1-3-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.3 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.3 brings many improvements to the language, the compiler and its tooling, specially Mix (Elixir's build tool) and ExUnit (Elixir's test framework).
 ---
diff --git a/_posts/2016-07-14-announcing-genstage.markdown b/_posts/2016-07-14-announcing-genstage.markdown
index 8b5bd31a5..7a853d043 100644
--- a/_posts/2016-07-14-announcing-genstage.markdown
+++ b/_posts/2016-07-14-announcing-genstage.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Announcing GenStage
-author: José Valim
+authors:
+-  José Valim
 category: Announcements
 excerpt: GenStage is a new Elixir behaviour for exchanging events with back-pressure between Elixir processes. In this blog post we will cover the background that led us to GenStage, some example use cases, and what we are exploring for future releases.
 ---
diff --git a/_posts/2017-01-05-elixir-v1-4-0-released.markdown b/_posts/2017-01-05-elixir-v1-4-0-released.markdown
index b333f5446..f110bb07e 100644
--- a/_posts/2017-01-05-elixir-v1-4-0-released.markdown
+++ b/_posts/2017-01-05-elixir-v1-4-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.4 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.4 brings many improvements to the language, its standard library and the Mix build tool.
 ---
diff --git a/_posts/2017-07-25-elixir-v1-5-0-released.markdown b/_posts/2017-07-25-elixir-v1-5-0-released.markdown
index 2fe2c2794..c4f38f788 100644
--- a/_posts/2017-07-25-elixir-v1-5-0-released.markdown
+++ b/_posts/2017-07-25-elixir-v1-5-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.5 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.5 integrates with Erlang/OTP 20 and bring changes that improves the language reach and the developer experience
 ---
diff --git a/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown b/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown
index 6aa52bf6e..242c28635 100644
--- a/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown
+++ b/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "StreamData: Property-based testing and data generation"
-author: Andrea Leopardi
+authors:
+-  Andrea Leopardi
 category: Announcements
 excerpt: We are working on data generation and property-based testing for the next versions of Elixir.
 ---
diff --git a/_posts/2018-01-17-elixir-v1-6-0-released.markdown b/_posts/2018-01-17-elixir-v1-6-0-released.markdown
index c9e15c14b..99bc8c441 100644
--- a/_posts/2018-01-17-elixir-v1-6-0-released.markdown
+++ b/_posts/2018-01-17-elixir-v1-6-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.6 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.6 includes a code formatter, defguard, dynamic supervision and new module attributes that improves code quality and the developer experience
 ---
diff --git a/_posts/2018-06-28-gsoc-projects.markdown b/_posts/2018-06-28-gsoc-projects.markdown
index 703275a59..168f6126e 100644
--- a/_posts/2018-06-28-gsoc-projects.markdown
+++ b/_posts/2018-06-28-gsoc-projects.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Google Summer of Code 2018 projects
-author: Andrea Leopardi
+authors:
+-  Andrea Leopardi
 category: Announcements
 excerpt: Once again Elixir is participating in Google Summer of Code 2018. In this post, we'll have a look at the active projects.
 ---
diff --git a/_posts/2018-07-25-elixir-v1-7-0-released.markdown b/_posts/2018-07-25-elixir-v1-7-0-released.markdown
index 8ae4cc12a..51e8f7a66 100644
--- a/_posts/2018-07-25-elixir-v1-7-0-released.markdown
+++ b/_posts/2018-07-25-elixir-v1-7-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.7 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.7 includes many quality of life improvements, focusing on documentation, Logger and ExUnit, as well as a new Elixir Core team member!
 ---
@@ -147,7 +148,7 @@ We have also seen important developments in other areas not directly related to
 
   * We have added [a "Development" section](https://elixir-lang.org/development.html) to the website, that outlines the Elixir team structure and goals
 
-  * [Elixir now has its own mini-documentary](http://doc.honeypot.io/elixir-documentary-2018/), by [Honeypot](https://www.honeypot.io/)
+  * [Elixir now has its own mini-documentary](https://www.youtube.com/watch?v=lxYFOM3UJzo) by Honeypot
 
   * We have already highlighted some of the improvements in the ExDoc tool. Another improvement worth mentioning is the syntax highlighting is now done in Elixir itself, via the [Makeup](https://github.com/tmbb/makeup) library. This gives us more control over the grammar, the style, and improves load times. If you would like to add support for other languages, [reach out](https://github.com/tmbb/makeup)!
 
diff --git a/_posts/2019-01-14-elixir-v1-8-0-released.markdown b/_posts/2019-01-14-elixir-v1-8-0-released.markdown
index 1443d5a10..6da84a7dc 100644
--- a/_posts/2019-01-14-elixir-v1-8-0-released.markdown
+++ b/_posts/2019-01-14-elixir-v1-8-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.8 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.8 comes with many improvements at the infrastructure level, improving compilation time, speeding up common patterns, and adding features around introspection of the system.
 ---
diff --git a/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown b/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown
index 3f3b4bead..3868b94e6 100644
--- a/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown
+++ b/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Mint, a new HTTP client for Elixir
-author: Eric Meadows-Jönsson
+authors:
+-  Eric Meadows-Jönsson
 category: Announcements
 excerpt: Mint is a new low-level HTTP client that aims to provide a small and functional core that others can build on top.
 ---
diff --git a/_posts/2019-06-24-elixir-v1-9-0-released.markdown b/_posts/2019-06-24-elixir-v1-9-0-released.markdown
index 09eb688d4..b1b72fd4c 100644
--- a/_posts/2019-06-24-elixir-v1-9-0-released.markdown
+++ b/_posts/2019-06-24-elixir-v1-9-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.9 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.9 is out with releases support, improved configuration and more.
 ---
diff --git a/_posts/2020-01-27-elixir-v1-10-0-released.markdown b/_posts/2020-01-27-elixir-v1-10-0-released.markdown
index 9a2c80966..f2eac58ce 100644
--- a/_posts/2020-01-27-elixir-v1-10-0-released.markdown
+++ b/_posts/2020-01-27-elixir-v1-10-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.10 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.10 is out with standard library, compiler, and releases improvements.
 ---
diff --git a/_posts/2020-08-20-embedded-elixir-at-farmbot.markdown b/_posts/2020-08-20-embedded-elixir-at-farmbot.markdown
index f2120208e..0471d047f 100644
--- a/_posts/2020-08-20-embedded-elixir-at-farmbot.markdown
+++ b/_posts/2020-08-20-embedded-elixir-at-farmbot.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Embedded Elixir at Farmbot
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Farmbot.
 logo: /images/cases/logos/farmbot.png
diff --git a/_posts/2020-09-24-paas-with-elixir-at-Heroku.markdown b/_posts/2020-09-24-paas-with-elixir-at-Heroku.markdown
index 357f61cdf..bf97dd5f3 100644
--- a/_posts/2020-09-24-paas-with-elixir-at-Heroku.markdown
+++ b/_posts/2020-09-24-paas-with-elixir-at-Heroku.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: PaaS with Elixir at Heroku
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Heroku.
 logo: /images/cases/logos/heroku.png
diff --git a/_posts/2020-10-06-elixir-v1-11-0-released.markdown b/_posts/2020-10-06-elixir-v1-11-0-released.markdown
index 1ee4274cc..7aaaefefb 100644
--- a/_posts/2020-10-06-elixir-v1-11-0-released.markdown
+++ b/_posts/2020-10-06-elixir-v1-11-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.11 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.11 is out with improvements to the compiler and tighter integration with Erlang/OTP
 ---
diff --git a/_posts/2020-10-08-real-time-communication-at-scale-with-elixir-at-discord.markdown b/_posts/2020-10-08-real-time-communication-at-scale-with-elixir-at-discord.markdown
index 669578ae6..ac4f42ef8 100644
--- a/_posts/2020-10-08-real-time-communication-at-scale-with-elixir-at-discord.markdown
+++ b/_posts/2020-10-08-real-time-communication-at-scale-with-elixir-at-discord.markdown
@@ -1,9 +1,11 @@
 ---
 layout: post
 title: Real time communication at scale with Elixir at Discord
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Discord.
+flagship: true
 logo: /images/cases/logos/discord.png
 tags: real-time genstage otp
 ---
diff --git a/_posts/2020-10-27-delivering-social-change-with-elixir-at-change.org.markdown b/_posts/2020-10-27-delivering-social-change-with-elixir-at-change.org.markdown
index 3261bc1da..8e58ec64c 100644
--- a/_posts/2020-10-27-delivering-social-change-with-elixir-at-change.org.markdown
+++ b/_posts/2020-10-27-delivering-social-change-with-elixir-at-change.org.markdown
@@ -1,9 +1,11 @@
 ---
 layout: post
 title: Delivering social change with Elixir at Change.org
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Change.org.
+flagship: true
 logo: /images/cases/logos/change.png
 tags: social broadway
 ---
diff --git a/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown b/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown
index 0f797ecd6..e699b459a 100644
--- a/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown
+++ b/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Real-time collaboration with Elixir at Slab
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Slab.
 logo: /images/cases/logos/slab.png
diff --git a/_posts/2020-12-10-integrating-travel-with-elixir-at-duffel.markdown b/_posts/2020-12-10-integrating-travel-with-elixir-at-duffel.markdown
index 1a2661571..44f8c66cb 100644
--- a/_posts/2020-12-10-integrating-travel-with-elixir-at-duffel.markdown
+++ b/_posts/2020-12-10-integrating-travel-with-elixir-at-duffel.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Integrating travel with Elixir at Duffel
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Duffel.
 logo: /images/cases/logos/duffel.png
diff --git a/_posts/2021-01-13-orchestrating-computer-vision-with-elixir-at-v7.markdown b/_posts/2021-01-13-orchestrating-computer-vision-with-elixir-at-v7.markdown
index 7dd1fa5f2..8e402cae7 100644
--- a/_posts/2021-01-13-orchestrating-computer-vision-with-elixir-at-v7.markdown
+++ b/_posts/2021-01-13-orchestrating-computer-vision-with-elixir-at-v7.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Orchestrating computer vision with Elixir at V7
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at V7.
 logo: /images/cases/logos/v7.png
diff --git a/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown b/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown
index 15afd237d..e105822f1 100644
--- a/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown
+++ b/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Social messaging with Elixir at Community
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Community.
 logo: /images/cases/logos/community.png
diff --git a/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown b/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown
index 892a8c6e1..dc81c1aa8 100644
--- a/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown
+++ b/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Marketing and sales intelligence with Elixir at PepsiCo
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at PepsiCo.
 logo: /images/cases/logos/pepsico.png
diff --git a/_posts/2021-05-19-elixir-v1-12-0-released.markdown b/_posts/2021-05-19-elixir-v1-12-0-released.markdown
index ef4144845..676f3d2e2 100644
--- a/_posts/2021-05-19-elixir-v1-12-0-released.markdown
+++ b/_posts/2021-05-19-elixir-v1-12-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.12 released
-author: José Valim
+authors:
+-  José Valim
 category: Releases
 excerpt: Elixir v1.12 is out with improvements to scripting, tighter Erlang/OTP 24 integration, stepped ranges, and dozen of new functions across the standard library
 ---
diff --git a/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown b/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown
index 591401f66..51244a2e2 100644
--- a/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown
+++ b/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Social virtual spaces with Elixir at Mozilla
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Mozilla.
 logo: /images/cases/logos/mozilla-hubs.png
diff --git a/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown b/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown
index 03a6a17b8..e0563549c 100644
--- a/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown
+++ b/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Bootstrapping a multiplayer server with Elixir at X-Plane
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at X-Plane.
 logo: /images/cases/logos/x-plane.png
diff --git a/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown b/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown
index d7d294fab..7326c7d57 100644
--- a/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown
+++ b/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Embracing open data with Elixir at the Ministry of Ecological Transition in France
-author: José Valim
+authors:
+-  José Valim
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at the Ministry of Ecological Transition in France.
 logo: /images/cases/logos/met-france.svg
diff --git a/_posts/2021-12-03-elixir-v1-13-0-released.markdown b/_posts/2021-12-03-elixir-v1-13-0-released.markdown
index a406c0790..486d27699 100644
--- a/_posts/2021-12-03-elixir-v1-13-0-released.markdown
+++ b/_posts/2021-12-03-elixir-v1-13-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.13 released
-author: José Valim
+authors:
+- José Valim
 category: Releases
 excerpt: Elixir v1.13 is out with a focus on developer tooling
 ---
diff --git a/_posts/2022-09-01-elixir-v1-14-0-released.markdown b/_posts/2022-09-01-elixir-v1-14-0-released.markdown
index 35fbb7414..7ae52d259 100644
--- a/_posts/2022-09-01-elixir-v1-14-0-released.markdown
+++ b/_posts/2022-09-01-elixir-v1-14-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.14 released
-author: Andrea Leopardi
+authors:
+- Andrea Leopardi
 category: Releases
 excerpt: Elixir v1.14 is out with a focus on debugging and developer experience
 ---
diff --git a/_posts/2022-10-05-my-future-with-elixir-set-theoretic-types.markdown b/_posts/2022-10-05-my-future-with-elixir-set-theoretic-types.markdown
index 15d873521..11f8d06c6 100644
--- a/_posts/2022-10-05-my-future-with-elixir-set-theoretic-types.markdown
+++ b/_posts/2022-10-05-my-future-with-elixir-set-theoretic-types.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "My Future with Elixir: set-theoretic types"
-author: José Valim
+authors:
+- José Valim
 category: Announcements
 excerpt: We announce and explore the possibilities for bringing set-theoretic types into Elixir.
 ---
diff --git a/_posts/2022-12-22-cheatsheets-and-8-other-features-in-exdoc-that-improve-the-developer-experience.markdown b/_posts/2022-12-22-cheatsheets-and-8-other-features-in-exdoc-that-improve-the-developer-experience.markdown
index 0c029806c..505bf15bf 100644
--- a/_posts/2022-12-22-cheatsheets-and-8-other-features-in-exdoc-that-improve-the-developer-experience.markdown
+++ b/_posts/2022-12-22-cheatsheets-and-8-other-features-in-exdoc-that-improve-the-developer-experience.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Cheatsheets and other 8 ExDoc features that improve the developer experience"
-author: Hugo Baraúna
+authors:
+- Hugo Baraúna
 category: Announcements
 excerpt: This post explains the motivation behind the new ExDoc Cheatsheet feature. It also highlights other ExDoc features that show how ExDoc has been evolving to make the documentation experience in Elixir better and better.
 ---
diff --git a/_posts/2023-03-09-embedded-and-cloud-elixir-at-sparkmeter.markdown b/_posts/2023-03-09-embedded-and-cloud-elixir-at-sparkmeter.markdown
index d7723ce84..2a5fa73ce 100644
--- a/_posts/2023-03-09-embedded-and-cloud-elixir-at-sparkmeter.markdown
+++ b/_posts/2023-03-09-embedded-and-cloud-elixir-at-sparkmeter.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Embedded and cloud Elixir for grid-management at Sparkmeter"
-author: Hugo Baraúna
+authors:
+- Hugo Baraúna
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at SparkMeter.
 logo: /images/cases/logos/sparkmeter.png
diff --git a/_posts/2023-06-19-elixir-v1-15-0-released.markdown b/_posts/2023-06-19-elixir-v1-15-0-released.markdown
index b3fda1747..ffc23b810 100644
--- a/_posts/2023-06-19-elixir-v1-15-0-released.markdown
+++ b/_posts/2023-06-19-elixir-v1-15-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.15 released
-author: José Valim
+authors:
+- José Valim
 category: Releases
 excerpt: Elixir v1.15 with improvements to compilation and boot times.
 ---
diff --git a/_posts/2023-06-22-type-system-updates-research-dev.markdown b/_posts/2023-06-22-type-system-updates-research-dev.markdown
index 98a6ec5e9..1765f7830 100644
--- a/_posts/2023-06-22-type-system-updates-research-dev.markdown
+++ b/_posts/2023-06-22-type-system-updates-research-dev.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Type system updates: moving from research into development"
-author: José Valim
+authors:
+- José Valim
 category: Announcements
 excerpt: A short status update on the effort to bring a type system into Elixir.
 ---
diff --git a/_posts/2023-09-20-strong-arrows-gradual-typing.markdown b/_posts/2023-09-20-strong-arrows-gradual-typing.markdown
index f3b4f4556..cd62f8c33 100644
--- a/_posts/2023-09-20-strong-arrows-gradual-typing.markdown
+++ b/_posts/2023-09-20-strong-arrows-gradual-typing.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Strong arrows: a new approach to gradual typing"
-author: José Valim
+authors:
+- José Valim
 category: Announcements
 excerpt: An introduction to strong arrows and how it leverages the Erlang VM to provide sound gradual typing.
 ---
diff --git a/_posts/2023-12-22-elixir-v1-16-0-released.markdown b/_posts/2023-12-22-elixir-v1-16-0-released.markdown
index 46480837e..6e4a61dca 100644
--- a/_posts/2023-12-22-elixir-v1-16-0-released.markdown
+++ b/_posts/2023-12-22-elixir-v1-16-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: Elixir v1.16 released
-author: José Valim
+authors:
+- José Valim
 category: Releases
 excerpt: Elixir v1.16 released with compiler diagnostics and extensive documentation
 ---
diff --git a/_posts/2024-03-05-veeps-elixir-case.markdown b/_posts/2024-03-05-veeps-elixir-case.markdown
index 7566c01ab..f0e60b7d1 100644
--- a/_posts/2024-03-05-veeps-elixir-case.markdown
+++ b/_posts/2024-03-05-veeps-elixir-case.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Scaling a streaming service to hundreds of thousands of concurrent viewers at Veeps"
-author: Hugo Baraúna
+authors:
+- Hugo Baraúna
 category: Elixir in Production
 excerpt: A case study of how Elixir is being used at Veeps.
 logo: /images/cases/logos/veeps.svg
diff --git a/_posts/2024-06-12-elixir-v1-17-0-released.markdown b/_posts/2024-06-12-elixir-v1-17-0-released.markdown
index 959030f55..c857c906e 100644
--- a/_posts/2024-06-12-elixir-v1-17-0-released.markdown
+++ b/_posts/2024-06-12-elixir-v1-17-0-released.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Elixir v1.17 released: set-theoretic data types, calendar durations, and Erlang/OTP 27 support"
-author: Andrea Leopardi
+authors:
+- Andrea Leopardi
 category: Releases
 excerpt: "Elixir v1.17 released: set-theoretic data types, calendar durations, and Erlang/OTP 27 support"
 ---
diff --git a/_posts/2024-08-15-welcome-elixir-language-server-team.markdown b/_posts/2024-08-15-welcome-elixir-language-server-team.markdown
index 8883da8dd..2df6af2d1 100644
--- a/_posts/2024-08-15-welcome-elixir-language-server-team.markdown
+++ b/_posts/2024-08-15-welcome-elixir-language-server-team.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Announcing the official Elixir Language Server team"
-author: José Valim
+authors:
+- José Valim
 category: Announcements
 excerpt: "Announcing the official Elixir Language Server team to work on the code intelligence infrastructure to be used across tools and editors"
 ---
diff --git a/_posts/2024-08-28-typing-lists-and-tuples.markdown b/_posts/2024-08-28-typing-lists-and-tuples.markdown
index c0998bf86..d8548371c 100644
--- a/_posts/2024-08-28-typing-lists-and-tuples.markdown
+++ b/_posts/2024-08-28-typing-lists-and-tuples.markdown
@@ -1,7 +1,8 @@
 ---
 layout: post
 title: "Typing lists and tuples in Elixir"
-author: José Valim
+authors:
+- José Valim
 category: Announcements
 excerpt: "This article explores the design decisions of typing lists and tuples in Elixir within a sound gradual type system"
 ---
@@ -157,13 +158,13 @@ Overall,
 
 ## Summary
 
-I hope this article outlines some of the design decisions as we bring a gradual type system to Elixir. Although supporting tuples and lists is a "table stakes" feature in most type systems, bringing them to Elixir was an opportunity to understand how the type system will interact with several language idioms, as well as provide a foundation for future decisions. The most important take aways are:
+I hope this article outlines some of the design decisions as we bring a gradual type system to Elixir. Although supporting tuples and lists is a "table stakes" feature in most type systems, bringing them to Elixir is an opportunity to understand how the type system will interact with several language idioms, as well as provide a foundation for future decisions. The most important take aways are:
 
 1. Type safety is a commitment from both sides. If you want your type system to find even more bugs through more precise types, you will need to prove more frequently that your programs are free of certain typing violations.
 
-2. Given not everything will be encoded as types, exceptions are important. Even in the presence of `option` types, it would not be beneficial for developers if `elem(tuple, index)` returned `:none` for negative indexes.
+2. It is not a goal of the type system to avoid all runtime errors. This would require either a type system that is too precise (and require more proofs) or it would require functions to mask hard errors (such as a negative index) as error values. Exceptions still play an important role in typed Elixir and, given they are modelled as structs, they will also be typed in the future.
 
-3. Elixir's convention of using the suffix `!` to encode the possibility of runtime exceptions for a valid domain (the input types) nicely complements the type system, as it can help static programs avoid the boilerplate of converting `:none`/`:error` into exceptions for unexpected scenarios.
+3. Elixir's convention of using the suffix `!` to provide variants that encode the possibility of runtime exceptions for a valid domain (the input types) nicely complements the type system, as it can help static programs avoid the boilerplate of converting `:none`/`:error` into exceptions for unexpected scenarios.
 
 4. Using `dynamic()` in function signatures is a mechanism available in Elixir's type system to signal that a function has dynamic behaviour and may raise runtime errors, allowing violations to be reported on programs that wish to remain fully static. Similar to how other static languages provide dynamic behaviour via `Any` or `Dynamic` types.
 
diff --git a/_posts/2024-12-19-elixir-v1-18-0-released.markdown b/_posts/2024-12-19-elixir-v1-18-0-released.markdown
new file mode 100644
index 000000000..22edc0364
--- /dev/null
+++ b/_posts/2024-12-19-elixir-v1-18-0-released.markdown
@@ -0,0 +1,218 @@
+---
+layout: post
+title: "Elixir v1.18 released: type checking of calls, LSP listeners, built-in JSON, and more"
+authors:
+- José Valim
+category: Releases
+excerpt: "Elixir v1.18 released: type checking of function calls, Language Server listeners, built-in JSON, ExUnit improvements, mix format --migrate, and more"
+---
+
+Elixir v1.18 is an impressive release with improvements across the two main efforts happening within the Elixir ecosystem right now: set-theoretic types and language servers. It also comes with built-in JSON support and adds new capabilities to its unit testing library. Let's go over each of those in detail.
+
+## Type inference of patterns and return types
+
+There are several updates in the typing department, so let's break them down.
+
+#### A type system? In my Elixir?
+
+There is an on-going [research and development](https://elixir-lang.org/blog/2023/06/22/type-system-updates-research-dev/) effort to bring static types to Elixir. Elixir's type system is:
+
+  * **sound** - the types inferred and assigned by the type system align with the behaviour of the program
+
+  * **gradual** - Elixir's type system includes the `dynamic()` type, which can be used when the type of a variable or expression is checked at runtime. In the absence of `dynamic()`, Elixir's type system behaves as a static one
+
+  * **developer friendly** - the types are described, implemented, and composed using basic set operations: unions, intersections, and negation (hence it is a set-theoretic type system)
+
+More interestingly, you can compose `dynamic()` with any type. For example, `dynamic(integer() or float())` means the type is either `integer()` or `float()` at runtime. This allows the type system to emit warnings if none of the types are satisfied, even in the presence of dynamism.
+
+#### What has already been done?
+
+[Elixir v1.17 was the first release to incorporate the type system in the compiler](https://elixir-lang.org/blog/2024/06/12/elixir-v1-17-0-released/). In particular, we have added support for primitive types (integer, float, binary, pids, references, ports), atoms, and maps. We also added type checking to a handful of operations related to those types, such as accessing fields in maps, as in `user.adress` (mind the typo), performing structural comparisons between structs, as in `my_date < ~D[2010-04-17]`, etc.
+
+#### What is new in v1.18?
+
+The most exciting change in Elixir v1.18 is type checking of function calls, alongside gradual inference of patterns and return types. To understand how this will impact your programs, consider the following code defined in `lib/user.ex`:
+
+```elixir
+defmodule User do
+  defstruct [:age, :car_choice]
+
+  def drive(%User{age: age, car_choice: car}, car_choices) when age >= 18 do
+    if car in car_choices do
+      {:ok, car}
+    else
+      {:error, :no_choice}
+    end
+  end
+
+  def drive(%User{}, _car_choices) do
+    {:error, :not_allowed}
+  end
+end
+```
+
+Elixir's type system will infer the `drive` function expects a `User` struct as input and returns either `{:ok, dynamic()}` or `{:error, :no_choice}` or `{:error, :not_allowed}`. Therefore, the following code
+
+```elixir
+User.drive({:ok, %User{}}, car_choices)
+```
+
+will emit a warning stating that we are passing an invalid argument:
+
+![Example of a warning when passing wrong argument to a function](/images/contents/type-warning-function-clause.png)
+
+Now consider the expression below. We are expecting the `User.drive/2` call to return `:error`, which cannot possibly be true:
+
+```elixir
+case User.drive(user, car_choices) do
+  {:ok, car} -> car
+  :error -> Logger.error("User cannot drive")
+end
+```
+
+Therefore the code above would emit the following warning:
+
+![Example of a warning when a case clause won't ever match](/images/contents/type-warning-case.png)
+
+Our goal is for the warnings to provide enough contextual information that lead to clear reports and that's an area we are actively looking for feedback. If you receive a warning that is unclear, please open up a bug report.
+
+Elixir v1.18 also augments the type system with support for tuples and lists, plus type checking of almost all Elixir language constructs, except `for`-comprehensions, `with`, and closures. Here is a non-exaustive list of the new violations that can be detected by the type system:
+
+  * if you define a pattern that will never match any argument, such as `def function(x = y, x = :foo, y = :bar)`
+
+  * matching or accessing tuples at an invalid index, such as `elem(two_element_tuple, 2)`
+
+  * if you have a branch in a `try` that will never match the given expression
+
+  * if you have a branch in a `cond` that always passes (except the last one) or always fails
+
+  * if you attempt to use the return value of a call to `raise/2` (which by definition returns no value)
+
+In summary, this release takes us further in our journey of providing type checking and type inference of existing Elixir programs, without requiring Elixir developers to explicitly add type annotations.
+
+For existing codebases with reasonable code coverage, most type system reports will come from uncovering dead code - code which won't ever be executed - as seen in a [few](https://github.com/phoenixframework/phoenix_live_view/commit/6c6e2aaf6a01957cc6bb8a27d2513bff273e8ca2) [distinct](https://github.com/elixir-ecto/postgrex/commit/3308f277f455ec64f2d0d7be6263f77f295b1325) [projects](https://github.com/phoenixframework/flame/commit/0c0c2875e42952d2691cbdb7928fc32f4715e746). A notable example is the type system ability to track how private functions are used throughout a module and then point out which clauses are unused:
+
+```elixir
+defmodule Example do
+  def public(x) do
+    private(Integer.parse(x))
+  end
+
+  defp private(nil), do: nil
+  defp private("foo"), do: "foo"
+  defp private({int, _rest}), do: int
+  defp private(:error), do: 0
+  defp private("bar"), do: "bar"
+end
+```
+
+![Example of a warning for unused private clauses](/images/contents/type-warning-private.png)
+
+Keep in mind the current implementation does not perform type inference of guards yet, which is an important source of typing information in programs. There is a lot the type system can learn about our codebases, that it does not yet. This brings us to the next topic.
+
+#### Future work
+
+The next Elixir release should improve the typing of maps, tuples, and closures, allowing us to type even more constructs. We also plan to fully type the `with` construct, `for`-comprehensions, as well as protocols.
+
+But more importantly, we want to focus on complete type inference of guards, which in turn will allow us to explore ideas such as redundant pattern matching clauses and exhaustiveness checks. Our goal with inference is to strike the right balance between developer experience, compilation times, and the ability of finding provable errors in existing codebases. You can learn more [about the trade-offs we made for inference in our documentation](https://hexdocs.pm/elixir/1.18/gradual-set-theoretic-types.html#type-inference).
+
+Future Elixir versions will introduce user-supplied type signatures, which should bring the benefits of a static type system without relying on inference. [Check our previous article on the overall milestones for more information](https://elixir-lang.org/blog/2023/06/22/type-system-updates-research-dev/).
+
+#### Sponsors
+
+The type system was made possible thanks to a partnership between [CNRS](https://www.cnrs.fr/) and [Remote](https://remote.com/). The development work is currently sponsored by [Fresha](https://www.fresha.com/) ([they are hiring!](https://www.fresha.com/careers/openings?department=engineering)), [Starfish*](https://starfish.team/), and [Dashbit](https://dashbit.co/).
+
+## Language server listeners
+
+Three months ago, we welcomed [the Official Language Server team](https://elixir-lang.org/blog/2024/08/15/welcome-elixir-language-server-team/), with the goal of unifying the efforts behind code intelligence, tools, and editors in Elixir. Elixir v1.18 brings new features on this front by introducing locks and listeners to its compilation. Let's understand what it means.
+
+At the moment, all language server implementations have their own compilation environment. This means that your project and dependencies during development are compiled once, for your own use, and then again for the language server. This duplicate effort could cause the language server experience to lag, when it could be relying on the already compiled artifacts of your project.
+
+This release addresses the issue by introducing a compiler lock, ensuring that only a single operating system running Elixir compiles your project at a given moment, and by providing the ability for one operating system process to listen to the compilation results of others. In other words, different Elixir instances can now communicate over the same compilation build, instead of racing each other.
+
+These enhancements do not only improve editor tooling, but they also directly benefit projects like IEx and Phoenix. Here is a quick snippet showing how to enable auto-reloading inside IEx, then running `mix compile` in one shell automatically reloads the module inside the IEx session:
+
+<video controls>
+  <source src="/images/contents/iex-auto-reload.mp4" type="video/mp4">
+  Your browser does not support the video tag.
+</video>
+
+## Built-in JSON
+
+[Erlang/OTP 27 added built-in support for JSON](https://www.erlang.org/doc/apps/stdlib/json.html) and we are now bringing it to Elixir. A new module, called [`JSON`](https://hexdocs.pm/elixir/1.18/JSON.html), has been added with functions to encode and decode JSON. Its most basic APIs reflect the ones [from the Jason project](https://hexdocs.pm/jason/Jason.html) (the de-facto JSON library in the Elixir community up to this point).
+
+A new protocol, called [`JSON.Encoder`](https://hexdocs.pm/elixir/1.18/JSON.Encoder.html), is also provided for those who want to customize how their own data types are encoded to JSON. You can also derive protocols for structs, with a single-line of code:
+
+```elixir
+@derive {JSON.Encoder, only: [:id, :name]}
+defstruct [:id, :name, :email]
+```
+
+The deriving API mirrors the one from `Jason`, helping those who want to migrate to the new `JSON` module.
+
+## Parameterized tests and ExUnit groups
+
+[ExUnit now supports parameterized tests](https://hexdocs.pm/ex_unit/1.18/ExUnit.Case.html#module-parameterized-tests). This allows your test modules to run multiple times under different parameters.
+
+For example, Elixir ships [a local, decentralized and scalable key-value process storage called `Registry`](https://hexdocs.pm/elixir/Registry.html). The registry can be partitioned and its implementation differs depending if partitioning is enabled or not. Therefore, during tests, we want to ensure both modes are exercised. With Elixir v1.18, we can achieve this by writing:
+
+```elixir
+defmodule Registry.Test do
+  use ExUnit.Case,
+    async: true,
+    parameterize: [
+      %{partitions: 1},
+      %{partitions: 8}
+    ]
+
+  # ... the actual tests ...
+end
+```
+
+Once specified, the number of partitions is available as part of the test configuration. For example, to start one registry per test with the correct number of partitions, you can write:
+
+```elixir
+  setup config do
+    partitions = config.partitions
+    name = :"#{config.test}_#{partitions}"
+    opts = [keys: :unique, name: name, partitions: partitions]
+    start_supervised!({Registry, opts})
+    opts
+  end
+```
+
+Prior to parameterized tests, Elixir resorted on code generation, which increased compilation times. Furthermore, ExUnit parameterizes the whole test modules, which also allows the different parameters to run concurrently if the `async: true` option is given. Overall, this features allows you to compile and run multiple scenarios more efficiently.
+
+Finally, ExUnit also comes with the ability of specifying test groups. While ExUnit supports running tests concurrently, those tests must not have shared state between them. However, in large applications, it may be common for some tests to depend on some shared state, and other tests to depend on a completely separate state. For example, part of your tests may depend on Cassandra, while others depend on Redis. Prior to Elixir v1.18, these tests could not run concurrently, but in v1.18 they might as long as they are assigned to different groups:
+
+```elixir
+defmodule MyApp.PGTest do
+  use ExUnit.Case, async: true, group: :pg
+
+  # ...
+end
+```
+
+Tests modules within the same group do not run concurrently, but across groups, they might.
+
+With features like async tests, suite partitioning, and now grouping, Elixir developers have plenty of flexibility to make the most use of their machine resources, both in development and in CI.
+
+## `mix format --migrate`
+
+The `mix format` command now supports an explicit `--migrate` flag, which will convert constructs that have been deprecated in Elixir to their latest version. Because this flag rewrites the AST, it is not guaranteed the migrated format will always be valid when used in combination with macros that also perform AST rewriting.
+
+As of this release, the following migrations are executed:
+
+  * Normalize parens in bitstring modifiers - it removes unnecessary parentheses in known bitstring modifiers, for example `<<foo::binary()>>` becomes `<<foo::binary>>`, or adds parentheses for custom modifiers, where `<<foo::custom_type>>` becomes `<<foo::custom_type()>>`.
+
+  * Charlists as sigils - formats charlists as `~c` sigils, for example `'foo'` becomes `~c"foo"`.
+
+  * `unless` as negated `if`s - rewrites `unless` expressions using `if` with a negated condition, for example `unless foo do` becomes `if !foo do`. We plan to deprecate `unless` in future releases.
+
+More migrations will be added in future releases to help us push towards more consistent codebases.
+
+## Summary
+
+Other notable changes include [`PartitionSupervisor.resize!/2`](https://hexdocs.pm/elixir/1.18/PartitionSupervisor.html#resize!/2), for resizing the number of partitions (aka processes) of a supervisor at runtime, [Registry.lock/3](https://hexdocs.pm/elixir/1.18/Registry.html#lock/3) for simple in-process key locks, PowerShell versions of `elixir` and `elixirc` scripts for better DX on Windows, and more. [See the CHANGELOG](https://hexdocs.pm/elixir/1.18/changelog.html) for the complete release notes.
+
+Happy coding!
diff --git a/_posts/2025-01-21-remote-elixir-case.markdown b/_posts/2025-01-21-remote-elixir-case.markdown
new file mode 100644
index 000000000..10d47c32d
--- /dev/null
+++ b/_posts/2025-01-21-remote-elixir-case.markdown
@@ -0,0 +1,111 @@
+---
+layout: post
+title: "Remote: growing from zero to unicorn with Elixir"
+authors:
+- Hugo Baraúna
+category: Elixir in Production
+excerpt: A case study of how Elixir is being used at Remote.
+flagship: true
+logo: /images/cases/logos/remote.png
+tags: growth team web
+---
+
+*Welcome to our series of [case studies about companies using Elixir in production](/cases.html).*
+
+Remote is the everywhere employment platform enabling companies to find, hire, manage, and pay people anywhere across the world.
+
+Founded in 2019, they reached unicorn status in just over two years and have continued their rapid growth trajectory since.
+
+Since day zero, Elixir has been their primary technology. Currently, their engineering organization as a whole consists of nearly 300 individuals.
+
+This case study focuses on their experience using Elixir in a high-growth environment.
+
+![Remote website screenshot](/images/cases/bg/remote.png)
+
+## Why Elixir?
+
+Marcelo Lebre, co-founder and president of Remote, had worked with many languages and frameworks throughout his career, often encountering the same trade-off: easy-to-code versus easy-to-scale.
+
+In 2015, while searching for alternatives, he discovered Elixir. Intrigued, Marcelo decided to give it a try and immediately saw its potential. At the time, Elixir was still in its early days, but he noticed how fast the community was growing, with support for packages and frameworks starting to show up aggressively.
+
+In December 2018, when Marcelo and his co-founder decided to start the company, they had to make a decision about the technology that would support their vision. Marcelo wanted to prioritize building a great product quickly without worrying about scalability issues from the start. He found Elixir to be the perfect match:
+
+> I wanted to focus on building a great product fast and not really worry about its scalability. Elixir was the perfect match—reliable performance, easy-to-read syntax, strong community, and a learning curve that made it accessible to new hires.
+>
+> \- 	Marcelo Lebre, Co-founder and President
+
+The biggest trade-off Marcelo identified was the smaller pool of Elixir developers compared to languages like Ruby or Python. However, he quickly realized that the quality of candidates more than made up for it:
+
+> The signal-to-noise ratio in the quality of Elixir candidates was much higher, which made the trade-off worthwhile.
+>
+> \- 	Marcelo Lebre, Co-founder and President
+
+## Growing with a monolithic architecture
+
+Remote operates primarily with a monolith, with Elixir in the backend and React in the front-end.
+
+The monolith enabled speed and simplicity, allowing the team to iterate quickly and focus on building features. However, as the company grew, they needed to invest in tools and practices to manage almost 180 engineers working in the same codebase.
+
+One practice was boundary enforcement. They used the [Boundary library](https://github.com/sasa1977/boundary) to maintain strict boundaries between modules and domains inside the codebase.
+
+Another key investment was optimizing their compilation time in the CI pipeline. Since their project has around 15,000 files, compiling it in every build would take too long. So, they implemented incremental builds in their CI pipeline, recompiling only the files affected by changes instead of the entire codebase.
+
+> I feel confident making significant changes in the codebase. The combination of using a functional language and our robust test suite allows us to keep moving forward without too much worry.
+>
+> \- André Albuquerque, Staff Engineer
+
+Additionally, as their codebase grew, the Elixir language continued to evolve, introducing better abstractions for developers working with large codebases. For example, with the release of Elixir v1.11, the [introduction of config/runtime.exs](/blog/2020/10/06/elixir-v1-11-0-released/) provided the Remote team with a better foundation for managing configuration. This enabled them to move many configurations from compile-time to runtime, significantly reducing unnecessary recompilations caused by configuration updates.
+
+## Infra-structure and operations
+
+One might expect Remote’s infrastructure to be highly complex, given their global scale and the size of their engineering team. Surprisingly, their setup remains relatively simple, reflecting a thoughtful balance between scalability and operational efficiency.
+
+Remote runs on AWS, using EKS (Elastic Kubernetes Service). The main backend (the monolith) operates in only five pods, each with 10 GB of memory. They use [Distributed Erlang](https://www.erlang.org/doc/system/distributed.html) to connect the nodes in their cluster, enabling seamless communication between processes running on different pods.
+
+For job processing, they rely on [Oban](https://github.com/oban-bg/oban), which runs alongside the monolith in the same pods.
+
+Remote also offers a public API for partners. While this API server runs separately from the monolith, it is the same application, configured to start a different part of its supervision tree. The separation was deliberate, as the team anticipated different load patterns for the API and wanted the flexibility to scale it independently.
+
+The database setup includes a primary PostgreSQL instance on AWS RDS, complemented by a read-replica for enhanced performance and scalability. Additionally, a separate Aurora PostgreSQL instance is dedicated to storing Oban jobs. Over time, the team has leveraged tools like PG Analyze to optimize performance, addressing bottlenecks such as long queries and missing indexes.
+
+This streamlined setup has proven resilient, even during unexpected spikes in workload. The team shared an episode where a worker’s job count unexpectedly grew by two orders of magnitude. Remarkably, the system handled the increase seamlessly, continuing to run as usual without requiring any design changes or manual intervention.
+
+> We once noticed two weeks later that a worker’s load had skyrocketed. But the scheduler worked fine, and everything kept running smoothly. That was fun.
+>
+> \- Alex Naser, Staff Engineer
+
+## Team organization and responsibilities
+
+Around 90% of their backend team works in the monolith, while the rest work in a few satellite services, also written in Elixir.
+
+Within the monolith, teams are organized around domains such as onboarding, payroll, and billing. Each team owns one or multiple domains.
+
+To streamline accountability in a huge monolith architecture, Remote invested heavily in team assignment mechanisms.
+
+They implemented a tagging system that assigns ownership down to the function level. This means any trace—whether sent to tools like Sentry or Datadog—carries a tag identifying the responsible team. This tagging also extends to endpoints, allowing teams to monitor their areas effectively and even set up dashboards for alerts, such as query times specific to their domain.
+
+The tagging system also simplifies CI workflows. When a test breaks, it’s automatically linked to the responsible team based on the Git commit. This ensures fast issue identification and resolution, removing the need for manual triaging.
+
+## Hiring and training
+
+Remote’s hiring approach prioritizes senior engineers, regardless of their experience with Elixir.
+
+During the hiring process, all candidates are required to complete a coding exercise in Elixir. For those unfamiliar with the language, a tailored version of the exercise is provided, designed to introduce them to Elixir while reflecting the challenges they would face if hired.
+
+Once hired, new engineers are assigned an engineering buddy to guide them through the onboarding process.
+
+For hires without prior Elixir experience, Remote developed an internal Elixir training camp, a curated collection of best practices, tutorials, and other resources to introduce new hires to the language and ecosystem. This training typically spans two to four weeks.
+
+After completing the training, engineers are assigned their first tasks—carefully selected tickets designed to build confidence and familiarity with the codebase.
+
+## Summing up
+
+Remote’s journey highlights how thoughtful technology, infrastructure, and team organization decisions can support rapid growth.
+
+By leveraging Elixir’s strengths, they built a monolithic architecture that balanced simplicity with scalability. This approach allowed their engineers to iterate quickly in the early stages while effectively managing the complexities of a growing codebase.
+
+Investments in tools like the Boundary library and incremental builds ensured their monolith remained efficient and maintainable even as the team and codebase scaled dramatically.
+
+Remote's relatively simple infrastructure demonstrates that scaling doesn't always require complexity. Their ability to easily handle unexpected workload spikes reflects the robustness of their architecture and operational practices.
+
+Finally, their focus on team accountability and streamlined onboarding allowed them to maintain high productivity while integrating engineers from diverse technical backgrounds, regardless of their prior experience with Elixir.
diff --git a/_posts/2025-02-26-elixir-openchain-certification.markdown b/_posts/2025-02-26-elixir-openchain-certification.markdown
new file mode 100644
index 000000000..76285ea70
--- /dev/null
+++ b/_posts/2025-02-26-elixir-openchain-certification.markdown
@@ -0,0 +1,72 @@
+---
+layout: post
+title: "Announcing Elixir OpenChain Certification"
+authors:
+  - Jonatan Männchen
+  - José Valim
+category: Announcements
+excerpt: "The Elixir project now meets OpenChain (ISO/IEC 5230). Each release ships with Source SBoMs in CycloneDX 1.6 and SPDX 2.3, plus attestation."
+tags: openchain compliance
+---
+
+We are pleased to share that the Elixir project now complies with
+[OpenChain][openchain] ([ISO/IEC 5230][iso_5230]), an international
+standard for open source license compliance. This step aligns with broader
+efforts to meet industry standards for supply chain and cybersecurity best
+practices.
+
+“Today’s announcement around Elixir’s conformance represents another significant
+example of community maturity,” says Shane Coughlan, OpenChain General Manager.
+“With projects - the final upstream - using ISO standards for compliance and
+security with increasing frequency, we are seeing a shift to longer-term
+improvements to trust in the supply chain.”
+
+## Why OpenChain Compliance Helps
+
+By following OpenChain (ISO/IEC 5230), we demonstrate clear processes around
+license compliance. This benefits commercial and community users alike, making
+Elixir easier to adopt and integrate with confidence.
+
+## Changes for Elixir Users
+
+Elixir has an automated release process where its artifacts are signed. This
+change strengthens this process by:
+
+- All future Elixir releases will include a Source SBoM in
+  [CycloneDX 1.6 or later][cyclonedx] and [SPDX 2.3 or later][spdx] formats.
+- Each release will be attested along with the Source SBoM.
+
+These additions offer greater transparency into the components and licenses of
+each release, supporting more rigorous supply chain requirements.
+
+## Changes for Contributors
+
+Contributing to Elixir remains largely the same, we have added more clarity and
+guidelines around it:
+
+- Contributions remain under the Apache-2.0 License. Other licenses cannot be
+  accepted.
+- The project now enforces the [Developer Certificate of Origin (DCO)][dco],
+  ensuring clarity around contribution ownership.
+
+Contributors will notice minimal procedural changes, as standard practices
+around licensing remain in place.
+
+For more details, see the [CONTRIBUTING guidelines][contributing].
+
+## Commitment
+
+These updates were made in collaboration with the
+[Erlang Ecosystem Foundation][erlef], reflecting a shared
+commitment to robust compliance and secure development practices. Thank you to
+everyone who supported this milestone. We appreciate the community’s ongoing
+contributions and look forward to continuing the growth of Elixir under these
+established guidelines.
+
+[openchain]: https://openchainproject.org/
+[erlef]: https://erlef.org/
+[spdx]: https://spdx.org/rdf/terms/
+[cyclonedx]: https://cyclonedx.org/specification/overview/
+[iso_5230]: https://www.iso.org/standard/81039.html
+[dco]: https://developercertificate.org/
+[contributing]: https://github.com/elixir-lang/elixir/blob/main/CONTRIBUTING.md
diff --git a/_posts/2025-03-25-cyanview-elixir-case.markdown b/_posts/2025-03-25-cyanview-elixir-case.markdown
new file mode 100644
index 000000000..520c476bb
--- /dev/null
+++ b/_posts/2025-03-25-cyanview-elixir-case.markdown
@@ -0,0 +1,102 @@
+---
+layout: post
+title: "Cyanview: Coordinating Super Bowl's visual fidelity with Elixir"
+authors:
+- Lars Wikman
+- José Valim
+category: Elixir in Production
+excerpt: A case study of how Elixir is being used at Cyanview.
+logo: /images/cases/logos/cyanview.png
+tags: superbowl mqtt
+---
+
+How do you coordinate visual fidelity across two hundred cameras for a live event like the Super Bowl?
+
+The answer is: by using the craft of camera shading, which involves adjusting each camera to ensure they match up in color, exposure and various other visual aspects. The goal is to turn the live event broadcast into a cohesive and consistent experience. For every angle used, you want the same green grass and the same skin tones. Everything needs to be very closely tuned across a diverse set of products and brands. From large broadcast cameras, drone cameras, and PTZ cameras to gimbal-held mirrorless cameras and more. This is what Cyanview does. Cyanview is a small Belgian company that sells products for the live video broadcast industry, and its primary focus is shading.
+
+Broadcast is a business where you only get one chance to prove that your tool is up to the task. Reliability is king. There can be no hard failures.
+
+A small team of three built a product so powerful and effective that it spread across the industry purely on the strength of its functionality. Without any marketing, it earned a reputation among seasoned professionals and became a staple at the world’s top live events. Cyanview's Remote Control Panel (RCP) is now used by specialist video operators on the Olympics, Super Bowl, NFL, NBA, ESPN, Amazon and many more. Even most fashion shows in Paris use Cyanview’s devices.
+
+These devices put Elixir right in the critical path for serious broadcast operations. By choosing Elixir, Cyanview gained best-in-class networking features, state-of-the-art resilience and an ecosystem that allowed fast iteration on product features.
+
+
+![Operating many displays with Cyanview products.](/images/cases/bg/cyanview-4.jpg "Operating many displays with Cyanview products.")
+
+
+## Why Elixir?
+
+The founding team of Cyanview primarily had experience with embedded development, and the devices they produce involve a lot of low-level C code and plenty of FPGA. This is due to the low-level details of color science and the really tight timing requirements.
+
+If you’ve ever worked with camera software, you know it can be a mixed bag. Even after going fully digital, much of it remained tied to analog systems or relied on proprietary connectivity solutions. Cyanview has been targeting IP (as in Internet Protocol) from early on. This means Cyanview's software can operate on commodity networks that work in well-known and well-understood ways. This has aligned well with an increase in remote production, partially due to the pandemic, where production crews operate from a central location with minimal crew on location. Custom radio frequency or serial wire protocols have a hard time scaling to cross-continent distances.
+
+This also paved the way for Elixir, as the Erlang VM was designed to communicate and coordinate millions of devices, reliably, over the network.
+
+Elixir was brought in by the developer Ghislain, who needed to build integrations with cameras and interact with the other bits of required video gear, with many different protocols over the network. The language comes with a lot of practical features for encoding and decoding binary data down to the individual bits. Elixir gave them a strong foundation and the tools to iterate fast.
+
+Ghislain has been building the core intellectual property of Cyanview ever since. While the physical device naturally has to be solid, reliable, and of high quality, a lot of the secret sauce ultimately lies in the massive number of integrations and huge amounts of reverse engineering. Thus, the product is able to work with as many professional camera systems and related equipment as possible. It is designed to be compatible with everything and anything a customer is using. Plus, it offers an API to ensure smooth integration with other devices.
+
+David Bourgeois, the founder of Cyanview, told us a story how these technical decisions alongside Elixir helped them tackle real-world challenges:
+
+"During the Olympics in China, a studio in Beijing relied on a large number of Panasonic PTZ cameras. Most of their team, however, was based in Paris and needed to control the cameras remotely to run various shows throughout the day. The problem? Panasonic’s camera protocols were never designed for internet use — they require precise timing and multiple messages for every adjustment. With network latency, that leads to timeouts, disconnects, and system failures... So they ended up placing our devices next to the cameras in Beijing and controlled them over IP from Paris — just as designed."
+
+
+![Cyanview RIO device mounted on a camera at a sports field.](/images/cases/bg/cyanview-2.jpg "Cyanview RIO device mounted on a camera at a sports field.")
+
+
+The devices in a given location communicate and coordinate on the network over a custom MQTT protocol. Over a hundred cameras without issue on a single Remote Control Panel (RCP), implemented on top of Elixir's network stack.
+
+
+## Technical composition
+
+The system as a whole consists of RCP devices running a Yocto Linux system, with most of the logic built in Elixir and C. While Python is still used for scripting and tooling, its role has gradually diminished. The setup also includes multiple microcontrollers and the on-camera device, all communicating over MQTT. Additionally, cloud relays facilitate connectivity, while dashboards and controller UIs provide oversight and control. The two critical devices are the RCP offering control on the production end and the RIO handling low-latency manipulation of the camera. Both run Elixir.
+
+The configuration UI is currently built in Elm, but - depending on priorities - it might be converted to [Phoenix LiveView](https://phoenixframework.org/) over time to reduce the number of languages in use. The controller web UI is already in LiveView, and it is performing quite well on a very low-spec embedded Linux machine.
+
+The cloud part of the system is very limited today, which is unusual in a world of SaaS. There are cloud relays for distributing and sharing camera control as well as forwarding network ports between locations and some related features, also built in Elixir, but cloud is not at the core of the business. The devices running Elixir on location form a cluster over IP using a custom MQTT-based protocol suited to the task and are talking to hundreds of cameras and other video devices.
+
+It goes without saying that integration with so much proprietary equipment comes with challenges. Some integrations are more reliable than others. Some devices are more common, and their quirks are well-known through hard-won experience. A few even have good documentation that you can reference while others offer mystery and constant surprises. In this context, David emphasizes the importance of Elixir's mechanisms for recovering from failures:
+
+"If one camera connection has a blip, a buggy protocol or the physical connection to a device breaks it is incredibly important that everything else keeps working. And this is where Elixir’s supervision trees provide a critical advantage."
+
+
+## Growth & team composition
+
+The team has grown over the 9 years that the company has been operating, but it did so at a slow and steady pace. On average, the company has added just one person per year. With nine employees at the time of writing, Cyanview supports some of the biggest broadcast events in the world.
+
+There are two Elixir developers on board: Daniil who is focusing on revising some of the UI as well as charting a course into more cloud functionality, and Ghislain, who works on cameras and integration. Both LiveView and Elm are used to power device UIs and dashboards.
+
+What’s interesting is that, overall, the other embedded developers say that they don't know much about Elixir and they don't use it in their day-to-day work. Nonetheless, they are very comfortable implementing protocols and encodings in Elixir. The main reason they haven’t fully learned the language is simply time — they have plenty of other work to focus on, and deep Elixir expertise hasn’t been necessary. After all, there’s much more to their work beyond Elixir: designing PCBs, selecting electronic components, reverse engineering protocols, interfacing with displays, implementing FPGAs, managing production tests, real productions and releasing firmware updates.
+
+
+## Innovation and customer focus
+
+![Operator using Cyanview RCP for a massive crowd in an arena.](/images/cases/bg/cyanview-3.jpg "Operator using Cyanview RCP for a massive crowd in an arena.")
+
+
+Whether it’s providing onboard cameras in 40+ cars during the 24 hours of Le Mans, covering Ninja Warrior, the Australian Open, and the US Open, operating a studio in the Louvre, being installed in NFL pylons, or connecting over 200 cameras simultaneously – the product speaks for itself. Cyanview built a device for a world that runs on top of IP, using Elixir, a language with networking and protocols deep in its bones. This choice enabled them to do both: implement support for all the equipment and provide features no one else had.
+
+By shifting from conventional local-area radio frequency, serial connections, and inflexible proprietary protocols to IP networking, Cyanview’s devices redefined how camera systems operate. Their feature set is unheard of in the industry: Unlimited multicam. Tally lights. Pan & Tilt control. Integration with color correctors. World-spanning remote production.
+
+The ease and safety of shipping new functionality have allowed the company to support new features very quickly. One example is the increasing use of mirrorless cameras on gimbals to capture crowd shots. Cyanview were able to prototype gimbal control, test it with a customer and validate that it worked in a very short amount of time. This quick prototyping and validation of features is made possible by a flexible architecture that ensures that critical fundamentals don't break.
+
+Camera companies that don't produce broadcast shading remotes, such as Canon or RED, recommend Cyanview to their customers. Rather than competing with most broadcast hardware companies, Cyanview considers itself a partner. The power of a small team, a quality product and powerful tools can be surprising. Rather than focusing on marketing, Cyanview works very closely with its customers by supporting the success of their events and providing in-depth customer service.
+
+
+## Looking back and forward
+
+When asked if he would choose Elixir again, David responded:
+
+"Yes. We've seen what the Erlang VM can do, and it has been very well-suited to our needs. You don't appreciate all the things Elixir offers out of the box until you have to try to implement them yourself. It was not pure luck that we picked it, but we were still lucky. Elixir turned out to bring a lot that we did not know would be valuable to us. And we see those parts clearly now."
+
+Cyanview hopes to grow the team more, but plans to do so responsibly over time. Currently there is a lot more to do than the small team can manage.
+
+Development is highly active, with complementary products already in place alongside the main RCP device, and the future holds even more in that regard. Cloud offerings are on the horizon, along with exciting hardware projects that build on the lessons learned so far. As these developments unfold, we’ll see Elixir play an increasingly critical role in some of the world’s largest live broadcasts.
+
+![Cyanview Remote Control Panels in a control room.](/images/cases/bg/cyanview-1.jpg "Cyanview Remote Control Panels in a control room.")
+
+
+## In summary
+
+A high-quality product delivering the right innovation at the right time in an industry that's been underserved in terms of good integration. Elixir provided serious leverage for developing a lot of integrations with high confidence and consistent reliability. In an era where productivity and lean, efficient teams are everything, Cyanview is a prime example of how Elixir empowers small teams to achieve an outsized impact.
+
diff --git a/_posts/2025-06-02-elixir-outreach-stipend-for-speakers.markdown b/_posts/2025-06-02-elixir-outreach-stipend-for-speakers.markdown
new file mode 100644
index 000000000..1bca122fc
--- /dev/null
+++ b/_posts/2025-06-02-elixir-outreach-stipend-for-speakers.markdown
@@ -0,0 +1,42 @@
+---
+layout: post
+title: "Elixir Outreach stipend for speakers and trainers"
+authors:
+- José Valim
+category: Announcements
+excerpt: "We announce the Elixir Outreach stipend in partnership with Dashbit, Oban, and the Erlang Ecosystem Foundation"
+---
+
+[Dashbit](https://dashbit.co), [Oban](https://oban.pro), and the [Erlang Ecosystem Foundation (EEF)](https://erlef.org) are glad to announce a new program, which we will trial over the next 12 months, called "Elixir Outreach". Our goal is to provide funds to community members who want to present Elixir and Erlang to other ecosystems and communities, while respecting our joint values.
+
+In a nutshell:
+
+* We will provide funds to community members to speak **in-person** about anything related to Elixir and the Erlang VM.
+
+* We will cover hotel and transportation costs for up to $700 USD. Please reach out, even if you expect to exceed that limit. This is our first time running the program and we're refining the budget.
+
+* The event must expect at least 150 attendees and happen outside of the Elixir, overall BEAM, and functional programming communities. In other words, we won't cover costs for attending Erlang, Elixir, or other BEAM/FP conferences nor meetups. Consider it as an opportunity to learn and bring external knowledge and experiences to the BEAM community.
+
+* You will be expected to send a report about your experience. The format and duration is up to you. We'd prefer that you write a blog post or an article sharing your overall experience with the involved communities. However, if you would prefer to only send it privately to us, that's fine too!
+
+The event should take place within your area. Our overall goal is to support multiple individuals, rather than drain our budget on a few long-distance flights (such as across coasts or continents). We are flexible on event location, distance, or type. If in doubt, reach out to [elixir_outreach at erlef dot org](mailto:elixir_outreach@erlef.org)
+
+Our initial budget of $7000 was donated by Dashbit ($5000) and Oban ($2000) to the Erlang Ecosystem Foundation (EEF), specifically for this program. The EEF will oversee the distribution of the funds.
+
+## Requesting a stipend
+
+To request a stipend, visit the [Erlang Ecosystem Foundation website and choose "Elixir Outreach" as the stipend type](https://erlef.org/stipends/form?type=elixir-outreach).
+
+Given we have limited funds, we cannot guarantee they will be available when you request them. We recommend reaching out to us before submitting or acceptance your talk. Therefore, by contacting us early, we can validate if the event matches the criteria above, ask questions, and earmark the funds. Once your talk is accepted, send us any itemized travel and accommodation costs so we can transfer the stipend to you, (not in excess of $700 USD).
+
+You can also request a stipend after your talk has already been accepted, but then there are no guarantees a stipend will be available.
+
+Our goal is to make this process simple and as straight-forward as possible. Although, we reserve the right to refuse a request for any reason. If in doubt, reach out to [elixir_outreach at erlef dot org](mailto:elixir_outreach@erlef.org).
+
+## Acknowledgements
+
+This is a new effort for all involved! Please be patient while we figure out the details.
+
+If you are looking for conferences to speak at, [Dave Aronson keeps a list of CFPs closing soon](https://www.codosaur.us/speaking/cfps-ending-soon) and there are likely others available. Note, we don’t necessarily endorse all of the conferences listed nor guarantee they meet the requirements above, but the list may help you get the ball rolling.
+
+Thanks to Parker Selbert, Shannon Selbert, Brian Cardarella, Alistair Woodman, and Lee Barney for feedback and helping make this a reality.
\ No newline at end of file
diff --git a/atom.xml b/atom.xml
index 09471fd0d..052b63a8e 100644
--- a/atom.xml
+++ b/atom.xml
@@ -15,11 +15,11 @@ elixir_url: http://elixir-lang.org
 <entry>
   <title>{{ post.title }}</title>
   <link href="{{ page.elixir_url }}{{ post.url }}"/>
-  {% if post.author %}
-  <author>
-    <name>{{ post.author }}</name>
-  </author>
-  {% endif %}
+  {% for author in post.authors %}
+    <author>
+      <name>{{ author }}</name>
+    </author>
+  {% endfor %}
   <updated>{{ post.date | date_to_xmlschema }}</updated>
   <id>{{ post.id }}</id>
   <content type="html">{{ post.content | xml_escape }}</content>
diff --git a/blog/index.html b/blog/index.html
index 196e39159..75d152e14 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -9,7 +9,7 @@
     <div class="hentry post">
       <div class="sticky-header">
         <h2 class="entry-title"><a class="spec" href="{{ post.url }}" title="{{ post.title }}" rel="bookmark">{{ post.title }}</a></h2>
-        <div class="byline">{{ post.date | date: "%B %d, %Y" }}{% if post.author %} · by {{ post.author}}{% endif %} . in {% for category in post.categories %}<a href="/blog/categories.html#{{category}}" class="category">{{ category }}</a>{% endfor %}</div>
+        <div class="byline">{{ post.date | date: "%B %d, %Y" }}{% if post.authors %} · by {{ post.authors | join: ", " }}{% endif %} · in {% for category in post.categories %}<a href="/blog/categories.html#{{category}}" class="category">{{ category }}</a>{% endfor %}</div>
       </div><!-- .sticky-header -->
 
       <div class="entry-summary">
diff --git a/cases.html b/cases.html
index 635b8b704..42d49e97a 100644
--- a/cases.html
+++ b/cases.html
@@ -9,8 +9,9 @@ <h1>Cases</h1>
 <p>Click on the cases below to learn more about how companies across different industries are using the power of Elixir and its ecosystem to create and grow their businesses. Cases are listed in the order they have been published.</p>
 
 <div class="cases-boxes">
-  {% assign sorted_posts = site.categories["Elixir in Production"] | sort: 'date' %}
+  {% assign sorted_posts = site.categories["Elixir in Production"] | sort: 'date' | reverse %}
   {% for post in sorted_posts %}
+    {%- if post.flagship %}
     <a class="cases-box" href="{{ post.url }}" title="Case: {{ post.title }}">
       {% if post.logo == nil %}
         <div class="cases-image" style="background-image: url('/images/cases/logos/default-image.png')"></div>
@@ -23,6 +24,23 @@ <h1>Cases</h1>
         {% endfor %}
       </div>
     </a>
+    {%- endif -%}
+  {% endfor %}
+  {% for post in sorted_posts %}
+    {%- unless post.flagship %}
+    <a class="cases-box" href="{{ post.url }}" title="Case: {{ post.title }}">
+      {% if post.logo == nil %}
+        <div class="cases-image" style="background-image: url('/images/cases/logos/default-image.png')"></div>
+      {% else %}
+        <div class="cases-image" style="background-image: url('{{ post.logo }}')"></div>
+      {% endif %}
+      <div class="cases-tag">
+        {% for tag in post.tags %}
+          <span>#{{tag}}</span>
+        {% endfor %}
+      </div>
+    </a>
+    {%- endunless -%}
   {% endfor %}
 </div>
 
diff --git a/images/cases/bg/cyanview-1.jpg b/images/cases/bg/cyanview-1.jpg
new file mode 100644
index 000000000..2e0b9ffcf
Binary files /dev/null and b/images/cases/bg/cyanview-1.jpg differ
diff --git a/images/cases/bg/cyanview-2.jpg b/images/cases/bg/cyanview-2.jpg
new file mode 100644
index 000000000..a6e7796e6
Binary files /dev/null and b/images/cases/bg/cyanview-2.jpg differ
diff --git a/images/cases/bg/cyanview-3.jpg b/images/cases/bg/cyanview-3.jpg
new file mode 100644
index 000000000..fbe3515f3
Binary files /dev/null and b/images/cases/bg/cyanview-3.jpg differ
diff --git a/images/cases/bg/cyanview-4.jpg b/images/cases/bg/cyanview-4.jpg
new file mode 100644
index 000000000..c14baed64
Binary files /dev/null and b/images/cases/bg/cyanview-4.jpg differ
diff --git a/images/cases/bg/remote.png b/images/cases/bg/remote.png
new file mode 100644
index 000000000..a4285ad4e
Binary files /dev/null and b/images/cases/bg/remote.png differ
diff --git a/images/cases/logos/cyanview.png b/images/cases/logos/cyanview.png
new file mode 100644
index 000000000..4fac3bf69
Binary files /dev/null and b/images/cases/logos/cyanview.png differ
diff --git a/images/cases/logos/remote.png b/images/cases/logos/remote.png
new file mode 100644
index 000000000..6e8db442f
Binary files /dev/null and b/images/cases/logos/remote.png differ
diff --git a/images/contents/iex-auto-reload.mp4 b/images/contents/iex-auto-reload.mp4
new file mode 100644
index 000000000..d21ad3f8b
Binary files /dev/null and b/images/contents/iex-auto-reload.mp4 differ
diff --git a/images/contents/type-warning-case.png b/images/contents/type-warning-case.png
new file mode 100644
index 000000000..118dad1f1
Binary files /dev/null and b/images/contents/type-warning-case.png differ
diff --git a/images/contents/type-warning-function-clause.png b/images/contents/type-warning-function-clause.png
new file mode 100644
index 000000000..4c2fa76dd
Binary files /dev/null and b/images/contents/type-warning-function-clause.png differ
diff --git a/images/contents/type-warning-private.png b/images/contents/type-warning-private.png
new file mode 100644
index 000000000..da05ab1cb
Binary files /dev/null and b/images/contents/type-warning-private.png differ
diff --git a/index.html b/index.html
index d7bfef0b5..66925b0e5 100644
--- a/index.html
+++ b/index.html
@@ -123,7 +123,7 @@ <h4>Functional programming</h4>
     <h4>Extensibility and DSLs</h4>
 
     <div class="entry-summary">
-      <p>Elixir has been designed to be extensible, allowing developers naturally extend the language to particular domains, in order to increase their productivity.</p>
+      <p>Elixir has been designed to be extensible, allowing developers to naturally extend the language to particular domains, in order to increase their productivity.</p>
 
       <p>As an example, let's write a simple test case using <a href="https://hexdocs.pm/ex_unit/">Elixir's test framework called ExUnit</a>:</p>
 
diff --git a/install.bat b/install.bat
new file mode 100755
index 000000000..a6e88101c
--- /dev/null
+++ b/install.bat
@@ -0,0 +1,207 @@
+@echo off
+REM See latest version at:
+REM https://github.com/elixir-lang/elixir-lang.github.com/blob/main/install.bat
+
+setlocal EnableDelayedExpansion
+
+set "otp_version="
+set "elixir_version="
+set "force=false"
+
+goto :main
+
+:usage
+echo Usage: install.bat elixir@ELIXIR_VERSION otp@OTP_VERSION [options]
+echo.
+echo ELIXIR_VERSION can be X.Y.Z, latest, or main.
+echo OTP_VERSION can be X.Y.Z or latest.
+echo.
+echo Options:
+echo.
+echo   -f, --force      Forces installation even if it was previously installed
+echo   -h, --help       Prints this help
+echo.
+echo Examples:
+echo.
+echo   install.bat elixir@1.16.3 otp@26.2.5.4
+echo   install.bat elixir@latest otp@latest
+echo   install.bat elixir@main otp@latest
+echo.
+goto :eof
+
+:main
+for %%i in (%*) do (
+  set arg=%%i
+
+  if "!arg:~0,7!" == "elixir@" (
+    set "elixir_version=!arg:~7!"
+  ) else if "!arg:~0,4!" == "otp@" (
+    set "otp_version=!arg:~4!"
+  ) else if "!arg!" == "-f" (
+    set "force=true"
+  ) else if "!arg!" == "--force" (
+    set "force=true"
+  ) else if "!arg!" == "-h" (
+    call :usage
+    exit /b 0
+  ) else if "!arg!" == "--help" (
+    call :usage
+    exit /b 0
+  ) else (
+    echo error: unknown argument !arg!
+    exit /b 1
+  )
+)
+
+if "%elixir_version%" == "" (
+  call :usage
+  echo error: missing elixir@VERSION argument
+  exit /b 1
+)
+
+if "%otp_version%" == "" (
+  call :usage
+  echo error: missing otp@VERSION argument
+  exit /b 1
+)
+
+if "!otp_version!" == "latest" (
+  set "url=https://github.com/erlang/otp/releases/latest"
+  for /f "tokens=2 delims= " %%a in ('curl -fsS --head "!url!" ^| findstr /I "^location:"') do set url=%%a
+  set "otp_version=!url:*releases/tag/OTP-=!"
+)
+
+if "!elixir_version!" == "latest" (
+  set "url=https://github.com/elixir-lang/elixir/releases/latest"
+  for /f "tokens=2 delims= " %%a in ('curl -fsS --head "!url!" ^| findstr /I "^location:"') do set url=%%a
+  set "elixir_version=!url:*releases/tag/v=!"
+)
+
+for /f "tokens=1 delims=." %%A in ("!otp_version!") do set "elixir_otp_release=%%A"
+for /f "tokens=1,2 delims=." %%A in ("!elixir_version!") do set "elixir_major_minor=%%A.%%B"
+
+if "%elixir_major_minor%" == "1.14" (
+  if %elixir_otp_release% GEQ 25 set "elixir_otp_release=25"
+) else if "%elixir_major_minor%" == "1.15" (
+  if %elixir_otp_release% GEQ 26 set "elixir_otp_release=26"
+) else if "%elixir_major_minor%" == "1.16" (
+  if %elixir_otp_release% GEQ 26 set "elixir_otp_release=26"
+) else if "%elixir_major_minor%" == "1.17" (
+  if %elixir_otp_release% GEQ 27 set "elixir_otp_release=27"
+) else if "%elixir_major_minor%" == "1.18" (
+  if %elixir_otp_release% GEQ 27 set "elixir_otp_release=27"
+) else if "%elixir_major_minor%" == "1.19" (
+  if %elixir_otp_release% GEQ 28 set "elixir_otp_release=28"
+) else (
+  if %elixir_otp_release% GEQ 28 set "elixir_otp_release=28"
+)
+
+set "root_dir=%USERPROFILE%\.elixir-install"
+set "tmp_dir=%root_dir%\tmp"
+mkdir %tmp_dir% 2>nul
+set "otp_dir=%root_dir%\installs\otp\%otp_version%"
+set "elixir_dir=%root_dir%\installs\elixir\%elixir_version%-otp-%elixir_otp_release%"
+
+call :install_otp
+if %errorlevel% neq 0 exit /b 1
+
+set /p="checking OTP... "<nul
+set "PATH=%otp_dir%\bin;%PATH%"
+"%otp_dir%\bin\erl.exe" -noshell -eval "io:put_chars(erlang:system_info(otp_release) ++ "" ok\n""), halt()."
+
+call :install_elixir
+if %errorlevel% neq 0 exit /b 1
+
+set /p="checking Elixir... "<nul
+call "%elixir_dir%\bin\elixir.bat" -e "IO.write(System.version())"
+echo. ok
+
+echo.
+echo If you are using powershell, run this (or add to your $PROFILE):
+echo.
+echo    $env:PATH = "$env:USERPROFILE\.elixir-install\installs\otp\!otp_version!\bin;$env:PATH"
+echo    $env:PATH = "$env:USERPROFILE\.elixir-install\installs\elixir\!elixir_version!-otp-%elixir_otp_release%\bin;$env:PATH"
+echo.
+echo If you are using cmd, run this:
+echo.
+echo    set PATH=%%USERPROFILE%%\.elixir-install\installs\otp\!otp_version!\bin;%%PATH%%
+echo    set PATH=%%USERPROFILE%%\.elixir-install\installs\elixir\!elixir_version!-otp-%elixir_otp_release%\bin;%%PATH%%
+echo.
+goto :eof
+
+:install_otp
+set "otp_zip=otp_win64_%otp_version%.zip"
+
+if "%force%" == "true" (
+  if exist "%otp_dir%" (
+    rmdir /s /q "%otp_dir%"
+  )
+)
+
+if not exist "%otp_dir%\bin" (
+  if exist "%otp_dir%" (
+    rmdir /s /q "%otp_dir%"
+  )
+
+  set otp_url=https://github.com/erlang/otp/releases/download/OTP-!otp_version!/%otp_zip%
+  echo downloading !otp_url!...
+  curl.exe -fsSLo %tmp_dir%\%otp_zip% "!otp_url!" || exit /b 1
+
+  echo unpacking %tmp_dir%\%otp_zip%
+  powershell -NoProfile -Command ^
+    "$ErrorActionPreference='Stop';" ^
+    "try {" ^
+    "  if (-not (Get-Command Expand-Archive -ErrorAction SilentlyContinue)) {" ^
+    "    Add-Type -AssemblyName System.IO.Compression.FileSystem;" ^
+    "    [System.IO.Compression.ZipFile]::ExtractToDirectory('%tmp_dir%\%otp_zip%', '%otp_dir%')" ^
+    "  } else {" ^
+    "    Expand-Archive -LiteralPath '%tmp_dir%\%otp_zip%' -DestinationPath '%otp_dir%' -Force" ^
+    "  }" ^
+    "} catch { Write-Error $_; exit 1 }"
+  del /f /q "%tmp_dir%\%otp_zip%"
+  cd /d "%otp_dir%"
+
+  if not exist "c:\windows\system32\vcruntime140.dll" (
+    echo Installing VC++ Redistributable...
+    .\vc_redist.exe /quiet /norestart
+  )
+)
+exit /b 0
+goto :eof
+
+:install_elixir
+set "elixir_zip=elixir-otp-!elixir_otp_release!.zip"
+
+if "%elixir_version%" == "main" (
+  rem Do not remove this comment
+  set "ref=main-latest"
+) else (
+  rem Do not remove this comment
+  set "ref=v%elixir_version%"
+)
+
+if "%force%" == "true" (
+  if exist "%elixir_dir%" (
+    rmdir /s /q "%elixir_dir%"
+  )
+)
+
+if not exist "%elixir_dir%\bin" (
+  set "elixir_url=https://github.com/elixir-lang/elixir/releases/download/%ref%/elixir-otp-%elixir_otp_release%.zip"
+  echo downloading !elixir_url!...
+  curl.exe -fsSLo "%tmp_dir%\%elixir_zip%" "!elixir_url!" || exit /b 1
+
+  echo unpacking %tmp_dir%\%elixir_zip%
+  powershell -NoProfile -Command ^
+    "$ErrorActionPreference='Stop';" ^
+    "try {" ^
+    "  if (-not (Get-Command Expand-Archive -ErrorAction SilentlyContinue)) {" ^
+    "    Add-Type -AssemblyName System.IO.Compression.FileSystem;" ^
+    "    [System.IO.Compression.ZipFile]::ExtractToDirectory('%tmp_dir%\%elixir_zip%', '%elixir_dir%')" ^
+    "  } else {" ^
+    "    Expand-Archive -LiteralPath '%tmp_dir%\%elixir_zip%' -DestinationPath '%elixir_dir%' -Force" ^
+    "  }" ^
+    "} catch { Write-Error $_; exit 1 }"
+  del /f /q %tmp_dir%\%elixir_zip%
+)
+goto :eof
diff --git a/install.markdown b/install.markdown
index 8c429772e..946d83f84 100644
--- a/install.markdown
+++ b/install.markdown
@@ -10,7 +10,7 @@ image: /images/social/elixir-og-card.jpg
 
 {% include toc.html %}
 
-The quickest way to install Elixir is through a distribution or using one of the available installers. If such an option is not available, then we recommend using the precompiled packages or compiling the language yourself. All of these options are detailed next.
+The quickest way to install Elixir is through install scripts, operating system package manager, or using one of the available installers. If such an option is not available, then we recommend using the precompiled packages or compiling the language yourself. All of these options are detailed next.
 
 Note that Elixir {{ stable.name }} requires Erlang {{ stable.minimum_otp }} or later. Many of the instructions below will automatically install Erlang for you. If they do not, the "Installing Erlang" section has you covered.
 
@@ -22,55 +22,29 @@ Install Elixir according to your operating system and tool of choice.
 
 ### macOS
 
+  - Using [install scripts](#install-scripts)
+
   - Using [Homebrew](https://brew.sh/):
     * Run: `brew install elixir`
 
   - Using [Macports](https://www.macports.org/):
     * Run: `sudo port install elixir`
 
-Note version managers (described below), are also available for macOS.
+  - Using [version managers](#version-managers)
 
 ### GNU/Linux
 
-On Unix systems, there are two options to install Elixir. You can use the Erlang/Elixir packages that are part of your distribution, although those may lag behind in version numbers (especially for LTS releases). In such cases, you can also opt to use a version manager.
-
-#### Version managers
-
-There are many tools that allow developers to install and manage multiple Erlang and Elixir versions. They are useful if you have multiple projects running on different Elixir or Erlang versions, can't install Erlang or Elixir as mentioned above or if the version provided by your package manager is outdated. Here are some of those tools:
-
-  * [asdf](https://github.com/asdf-vm/asdf) - install and manage different [Elixir](https://github.com/asdf-vm/asdf-elixir) and [Erlang](https://github.com/asdf-vm/asdf-erlang) versions
-  * [kiex](https://github.com/taylor/kiex) - install and manage different Elixir versions
-  * [kerl](https://github.com/yrashk/kerl) - install and manage different Erlang versions
-
-Keep in mind that each Elixir version supports specific Erlang/OTP versions. [See the supported versions alongside our docs](/docs).
+Below we list steps for installing Elixir in different distributions. If your distribution is not listed or the steps below do not work, you may consider using [version managers](#version-managers).
 
 #### Distributions
 
-  - **Alpine Linux** (Community repository)
-    * Run: `apk add elixir`
-
   - **Arch Linux** (Community repository)
     * Run: `pacman -S elixir`
 
-  - **Debian**
-    * Run: `sudo apt install erlang-dev elixir`
-
-  - **Debian** (and **Ubuntu**) alternative
-    * Use the [RabbitMQ Packages](https://launchpad.net/~rabbitmq) (might not be up-to-date however likely newer than the distribution)
-
-      ```bash
-      $ sudo add-apt-repository ppa:rabbitmq/rabbitmq-erlang
-      $ sudo apt update
-      $ sudo apt install elixir erlang-dev erlang-xmerl
-      ```
-
-  - **Fedora 21 (and older)**
-    * Run: `sudo yum install elixir`
-
-  - **Fedora 22 (and newer)**
-    * Run: `sudo dnf install elixir erlang`
+  - **Fedora**
+    * Fedora's Rawhide repository keeps more recent versions: `sudo dnf --repo=rawhide install elixir elixir-doc erlang erlang-doc`
+    * You may use the default distribution, but those often lag behind: `sudo dnf install elixir erlang`
     * Documentation is available in separate packages: `sudo dnf install elixir-doc erlang-doc`
-    * Fedora's Rawhide repository has newer versions before they go into the main repositories: `sudo dnf --disablerepo='*' --enablerepo=rawhide install elixir elixir-doc erlang erlang-doc`
 
   - **Gentoo**
     * Run: `emerge --ask dev-lang/elixir`
@@ -78,25 +52,24 @@ Keep in mind that each Elixir version supports specific Erlang/OTP versions. [Se
   - **GNU Guix**
     * Run: `guix package -i elixir`
 
-  - **openSUSE (and SLES)**
-    * Add Elixir/Erlang repository: `zypper ar -f obs://devel:languages:erlang/ Elixir-Factory`
-    * Run: `zypper in elixir`
-    * Optional: if you want to use the latest Erlang, you can use this repository: `zypper ar -f  obs://devel:languages:erlang:Factory Erlang-Factory`
+  - **Ubuntu**
+    * Use [install scripts](#install-scripts) (or alternatively [version managers](#version-managers))
+    * The packages in `apt` tend to lag several versions behind. You may use [RabbitMQ Packages](https://launchpad.net/~rabbitmq) outlined below, which are likely newer than `apt`:
+
+      ```bash
+      $ sudo add-apt-repository ppa:rabbitmq/rabbitmq-erlang
+      $ sudo apt update
+      $ sudo apt install git elixir erlang
+      ```
 
-  - **Slackware**
-    * Using Sbopkg:
-      * Run: `sbopkg -ki "erlang-otp elixir"`
-    * Manually:
-      * Download, build and install from SlackBuilds.org: [`erlang-otp`](https://slackbuilds.org/repository/14.2/development/erlang-otp/), and [`elixir`](https://slackbuilds.org/repository/14.2/development/elixir)
+#### Version managers
 
-  - **Solus**
-    * Run: `eopkg install elixir`
+There are many tools that allow developers to install and manage multiple Erlang and Elixir versions. They are useful if you have multiple projects running on different Elixir or Erlang versions, can't install Erlang or Elixir as mentioned above or if the version provided by your package manager is outdated. Here are some of those tools:
 
-  - **Ubuntu**
-    * Run: `sudo apt install elixir`
+  * [asdf](https://github.com/asdf-vm/asdf) - install and manage different [Elixir](https://github.com/asdf-vm/asdf-elixir) and [Erlang](https://github.com/asdf-vm/asdf-erlang) versions
+  * [kerl](https://github.com/kerl/kerl) - install and manage different Erlang versions
 
-  - **Void Linux**
-    * Run: `xbps-install -S elixir`
+Keep in mind that each Elixir version supports specific Erlang/OTP versions. [See the supported versions alongside our docs](/docs).
 
 ### BSD
 
@@ -122,6 +95,8 @@ Keep in mind that each Elixir version supports specific Erlang/OTP versions. [Se
 {% endfor %}
       Run `erl` in the terminal if you are unsure of your Erlang/OTP version.<br />Previous Elixir versions are available in our [Releases](https://github.com/elixir-lang/elixir/releases) page.
 
+  - Using [install scripts](#install-scripts)
+
   - Using [Scoop](https://scoop.sh/):
     * Install Erlang: `scoop install erlang`
     * Install Elixir: `scoop install elixir`
@@ -129,8 +104,6 @@ Keep in mind that each Elixir version supports specific Erlang/OTP versions. [Se
   - Using [Chocolatey](https://community.chocolatey.org/):
     * Install Elixir (installs Erlang as a dependency): `choco install elixir`
 
-Elixir versions before v1.15 can also be installed using the deprecated [Online Elixir Installer](https://github.com/elixir-lang/elixir-windows-setup/releases/tag/v2.4).
-
 ### Raspberry Pi and embedded devices
 
 To build and package an Elixir application, with the whole operating system, and burn that into a disk or deploy it overwhere, [check out the Nerves project](https://www.nerves-project.org).
@@ -148,6 +121,34 @@ If you are familiar with Docker you can use the official Docker image to get sta
 
 The above will automatically point to the latest Erlang and Elixir available. For production usage, we recommend using [Hex.pm Docker images](https://hub.docker.com/r/hexpm/elixir), which are immutable and point to a specific Erlang and Elixir version.
 
+## Install scripts
+
+Elixir and Erlang/OTP can be quickly installed for macOS, Windows, or Ubuntu using an `install.sh`/`install.bat` script:
+
+If you are using bash (macOS/Ubuntu/Windows), run:
+
+```sh
+curl -fsSO {{ site.url }}/install.sh
+sh install.sh elixir@{{ stable.version }} otp@{{ stable.recommended_otp }}
+installs_dir=$HOME/.elixir-install/installs
+export PATH=$installs_dir/otp/{{ stable.recommended_otp }}/bin:$PATH
+export PATH=$installs_dir/elixir/{{ stable.version }}-otp-{{ stable.otp_versions[0] }}/bin:$PATH
+iex
+```
+
+If you are using PowerShell (Windows), run:
+
+```pwsh
+curl.exe -fsSO {{ site.url }}/install.bat
+.\install.bat elixir@{{ stable.version }} otp@{{ stable.recommended_otp }}
+$installs_dir = "$env:USERPROFILE\.elixir-install\installs"
+$env:PATH = "$installs_dir\otp\{{ stable.recommended_otp }}\bin;$env:PATH"
+$env:PATH = "$installs_dir\elixir\{{ stable.version }}-otp-{{ stable.otp_versions[0] }}\bin;$env:PATH"
+iex.bat
+```
+
+You may want to [set the $PATH environment variable](#setting-path-environment-variable) for your whole system. Use `install.sh --help` or `install.bat --help` to learn more about available arguments and options.
+
 ## Precompiled package
 
 Elixir provides a precompiled package for every release. First [install Erlang](/install.html#installing-erlang) and then download the appropriate precompiled Elixir below. You can consult your Erlang/OTP version by running `erl -s halt`:
diff --git a/install.sh b/install.sh
new file mode 100755
index 000000000..f1647a15f
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,298 @@
+#!/bin/sh
+# See latest version at:
+# https://github.com/elixir-lang/elixir-lang.github.com/blob/main/install.sh
+
+set -eu
+
+otp_version=
+elixir_version=
+force=false
+
+usage() {
+  cat<<EOF
+Usage: install.sh elixir@ELIXIR_VERSION otp@OTP_VERSION [options]
+
+ELIXIR_VERSION can be X.Y.Z, latest, or main.
+OTP_VERSION can be X.Y.Z, latest, master, maint, or maint-RELEASE (e.g. maint-27).
+
+Options:
+
+  -f, --force      Forces installation even if it was previously installed
+  -h, --help       Prints this help
+
+Examples:
+
+  sh install.sh elixir@1.16.3 otp@26.2.5.4
+  sh install.sh elixir@latest otp@latest
+  sh install.sh elixir@main otp@master
+
+EOF
+}
+
+main() {
+  for arg in "$@"; do
+    case "$arg" in
+      elixir@*)
+        elixir_version="${arg#elixir@}"
+        ;;
+      otp@*)
+        otp_version="${arg#otp@}"
+        ;;
+      -h|--help)
+        usage
+        exit 0
+        ;;
+      -f|--force)
+        force=true
+        ;;
+      *)
+        echo "error: invalid argument $arg" >&2
+        exit 1
+        ;;
+    esac
+  done
+
+  if [ -z "${elixir_version}" ]; then
+    usage
+    echo "error: missing elixir@VERSION argument"
+    exit 1
+  fi
+
+  if [ -z "${otp_version}" ]; then
+    usage
+    echo "error: missing otp@VERSION argument"
+    exit 1
+  fi
+
+  root_dir="$HOME/.elixir-install"
+  tmp_dir="$root_dir/tmp"
+  mkdir -p "$tmp_dir"
+
+  if [ "${otp_version}" = latest ]; then
+    url=$(curl -fsS --head https://github.com/erlef/otp_builds/releases/latest | grep -i '^location:' | awk '{print $2}' | tr -d '\r\n')
+    tag=$(basename "$url")
+    otp_version="${tag#OTP-}"
+  fi
+
+  if [ "${elixir_version}" = latest ]; then
+    url=$(curl -fsS --head https://github.com/elixir-lang/elixir/releases/latest | grep -i '^location:' | awk '{print $2}' | tr -d '\r\n')
+    tag=$(basename "$url")
+    elixir_version="${tag#v}"
+  fi
+
+  case "${otp_version}" in
+    master|maint*)
+      branch_version=$(curl -fsS https://raw.githubusercontent.com/erlang/otp/refs/heads/${otp_version}/OTP_VERSION | tr -d '\n')
+      elixir_otp_release="${branch_version%%.*}"
+      ;;
+    *)
+      elixir_otp_release="${otp_version%%.*}"
+      ;;
+  esac
+
+  case "$elixir_version" in
+    1.14.*)
+      [ "${elixir_otp_release}" -ge 25 ] && elixir_otp_release=25
+      ;;
+    1.15.*|1.16.*)
+      [ "${elixir_otp_release}" -ge 26 ] && elixir_otp_release=26
+      ;;
+    1.17.*|1.18.*)
+      [ "${elixir_otp_release}" -ge 27 ] && elixir_otp_release=27
+      ;;
+    1.19.*)
+      [ "${elixir_otp_release}" -ge 28 ] && elixir_otp_release=28
+      ;;
+    *)
+      [ "${elixir_otp_release}" -ge 28 ] && elixir_otp_release=28
+      ;;
+  esac
+
+  otp_dir="$root_dir/installs/otp/$otp_version"
+  elixir_dir="${root_dir}/installs/elixir/${elixir_version}-otp-${elixir_otp_release}"
+
+  if unzip_available; then
+    install_otp &
+    pid_otp=$!
+
+    install_elixir &
+    pid_elixir=$!
+
+    wait $pid_otp
+    wait $pid_elixir
+  else
+    # if unzip is missing (e.g. official docker ubuntu image), install otp and elixir
+    # serially because we unzip elixir using OTP zip:extract/2.
+    install_otp
+    install_elixir
+  fi
+
+  printf "checking OTP... "
+  export PATH="$otp_dir/bin:$PATH"
+  erl -noshell -eval 'io:put_chars(erlang:system_info(otp_release) ++ " ok\n"), halt().'
+
+  printf "checking Elixir... "
+  "$elixir_dir/bin/elixir" -e 'IO.puts(System.version() <> " ok")'
+
+  export PATH="$elixir_dir/bin:$PATH"
+cat<<EOF
+
+Run this (or add to your ~/.bashrc or similar file):
+
+    export PATH=\$HOME/.elixir-install/installs/otp/$otp_version/bin:\$PATH
+    export PATH=\$HOME/.elixir-install/installs/elixir/$elixir_version-otp-$elixir_otp_release/bin:\$PATH
+
+EOF
+}
+
+install_otp() {
+  os=$(uname -sm)
+  case "$os" in
+    "Darwin x86_64") target=x86_64-apple-darwin ;;
+    "Darwin arm64")  target=aarch64-apple-darwin ;;
+    "Linux x86_64")  target=x86_64-pc-linux ;;
+    "Linux aarch64") target=aarch64-pc-linux ;;
+    MINGW64*)        target=x86_64-pc-windows ;;
+    *) echo "error: unsupported system $os." && exit 1 ;;
+  esac
+
+  if [ ! -d "${otp_dir}/bin" ] || [ "$force" = true ]; then
+    rm -rf "${otp_dir}"
+
+    case "$target" in
+      *windows) install_otp_windows ;;
+      *darwin) install_otp_darwin ;;
+      *linux) install_otp_linux ;;
+    esac
+  fi
+}
+
+install_otp_darwin() {
+  case "${otp_version}" in
+    master|maint*)
+      ref="${otp_version}-latest"
+      ;;
+    *)
+      ref="OTP-${otp_version}"
+      ;;
+  esac
+
+  otp_tgz="otp-${target}.tar.gz"
+  url="https://github.com/erlef/otp_builds/releases/download/$ref/$otp_tgz"
+
+  download "$url" "$tmp_dir/$otp_tgz"
+
+  echo "unpacking $otp_tgz to $otp_dir..."
+  mkdir -p "$otp_dir"
+  tar xzf "$tmp_dir/$otp_tgz" -C "$otp_dir"
+  rm "$tmp_dir/$otp_tgz"
+}
+
+install_otp_linux() {
+  case "${otp_version}" in
+    master|maint*)
+      otp_tgz="${otp_version}.tar.gz"
+      ;;
+    *)
+      otp_tgz="OTP-${otp_version}.tar.gz"
+      ;;
+  esac
+
+  case "$target" in
+    x86_64*)  arch=amd64 ;;
+    aarch64*) arch=arm64 ;;
+  esac
+
+  id=$(grep '^ID=' /etc/os-release | cut -d '=' -f 2)
+  if [ "${id}" != ubuntu ]; then
+    echo $id is not supported
+    exit 1
+  fi
+  case $(grep '^VERSION_ID=' /etc/os-release | cut -d '"' -f 2) in
+    20*|21*)
+      lts=20.04
+      ;;
+    22*|23*)
+      lts=22.04
+      ;;
+    *)
+      lts=24.04
+      ;;
+  esac
+
+  url="https://builds.hex.pm/builds/otp/${arch}/ubuntu-${lts}/$otp_tgz"
+  download "$url" "$tmp_dir/$otp_tgz"
+
+  echo "unpacking $otp_tgz to $otp_dir..."
+  mkdir -p "$otp_dir"
+  tar xzf "$tmp_dir/$otp_tgz" --strip-components 1 -C "$otp_dir"
+  (cd "$otp_dir" && ./Install -sasl "$PWD")
+  rm "$tmp_dir/$otp_tgz"
+}
+
+install_otp_windows() {
+  otp_zip="otp_win64_$otp_version.zip"
+  url="https://github.com/erlang/otp/releases/download/OTP-$otp_version/$otp_zip"
+  download "$url" "$tmp_dir/$otp_zip"
+
+  echo "unpacking $otp_zip to $otp_dir..."
+  mkdir -p "$otp_dir"
+  unzip -q "$tmp_dir/$otp_zip" -d "$otp_dir"
+  rm "$tmp_dir/$otp_zip"
+  install_vc_redist
+}
+
+install_vc_redist() {
+  if [ ! -f /c/windows/system32/vcruntime140.dll ]; then
+    echo "installing VC++ Redistributable..."
+    (cd $otp_dir && ./vc_redist.exe /quiet /norestart)
+  fi
+}
+
+install_elixir() {
+  elixir_zip="elixir-otp-$elixir_otp_release.zip"
+
+  if [ ! -d "${elixir_dir}/bin" ] || [ "$force" = true ]; then
+    case "${elixir_version}" in
+      main)
+        ref="${elixir_version}-latest"
+        ;;
+      v[0-9]*.[0-9])
+        ref="v${elixir_version}-latest"
+        ;;
+      *)
+        ref="v${elixir_version}"
+        ;;
+    esac
+
+    url="https://github.com/elixir-lang/elixir/releases/download/$ref/$elixir_zip"
+    download "$url" "$tmp_dir/$elixir_zip"
+
+    echo "unpacking $elixir_zip to $elixir_dir..."
+    rm -rf "${elixir_dir}"
+    mkdir -p "${elixir_dir}"
+
+    if unzip_available; then
+      unzip -q "${tmp_dir}/${elixir_zip}" -d "${elixir_dir}"
+    else
+      "${otp_dir}/bin/erl" -noshell -eval \
+        '[Zip,Dir] = init:get_plain_arguments(), {ok,_} = zip:unzip(Zip, [{cwd, Dir}]), halt().' \
+        -- "${tmp_dir}/${elixir_zip}" "${elixir_dir}"
+    fi
+
+    rm "${tmp_dir}/${elixir_zip}"
+  fi
+}
+
+download() {
+  url="$1"
+  output="$2"
+  echo "downloading $url"
+  curl --retry 3 -fsSLo "$output" "$url"
+}
+
+unzip_available() {
+  which unzip >/dev/null 2>&1
+}
+
+main "$@"
diff --git a/learning.markdown b/learning.markdown
index 0c5df683b..c78d1ba5a 100644
--- a/learning.markdown
+++ b/learning.markdown
@@ -281,11 +281,11 @@ Elixir koans is a fun, easy way to get started with the Elixir programming langu
 
 <div class="clear"></div>
 
-<h4 class="resource">Exercism.io<span class="free">free</span></h4>
+<h4 class="resource">Exercism<span class="free">free</span></h4>
 
-<a class="cover" href="https://exercism.io/tracks/elixir" title="Elixir Track on Exercism.io"> <img src="https://assets.exercism.io/tracks/elixir-bordered-turquoise.png" alt="Exercism.io Elixir track" width="190" /></a>
+<a class="cover" href="https://exercism.org/tracks/elixir" title="Elixir Track on Exercism"> <img src="https://assets.exercism.org/tracks/elixir.svg" alt="Exercism Elixir track" width="190" /></a>
 
-Exercism.io is an open source platform that provides free practice and mentoring in many languages, including Elixir.
+Exercism is an open source platform that provides free practice and mentoring in many languages, including Elixir.
 It features exercises of varying difficulty, from string processing to using OTP, that are mentored by volunteers.
 Once you have completed an exercise you can also view other students' solutions.
 
