<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adrien Poly</title>
    <description>The latest articles on DEV Community by Adrien Poly (@adrienpoly).</description>
    <link>https://dev.to/adrienpoly</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F98872%2F10f9cca5-94aa-4e60-8b9f-88e42b01a271.jpeg</url>
      <title>DEV Community: Adrien Poly</title>
      <link>https://dev.to/adrienpoly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrienpoly"/>
    <language>en</language>
    <item>
      <title>Deploying a Rails App with Kamal on Hetzner: A Beginner's Guide</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Fri, 09 Jun 2023 19:37:31 +0000</pubDate>
      <link>https://dev.to/adrienpoly/deploying-a-rails-app-with-mrsk-on-hetzner-a-beginners-guide-39kp</link>
      <guid>https://dev.to/adrienpoly/deploying-a-rails-app-with-mrsk-on-hetzner-a-beginners-guide-39kp</guid>
      <description>&lt;p&gt;Hello there!&lt;/p&gt;

&lt;p&gt;I was curious about Kamal and wanted to give it a try to host a simple application on a cheap VPS. With this guide, I'll walk you through the process step by step that I used to create and deploy your first Rails application with KAMAL on a Hetzner VPS. &lt;/p&gt;

&lt;p&gt;For this tutorial, we'll keep things as simple as possible. We'll deploy an application that uses an SQLite database.&lt;/p&gt;

&lt;p&gt;What you will need first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Docker account with an Api key&lt;/li&gt;
&lt;li&gt;an Hetzner account &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assuming you have that ready you should be able to deploy you first app with &lt;code&gt;Kamal&lt;/code&gt; in less than 10 minutes&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaffold a Rails Application
&lt;/h2&gt;

&lt;p&gt;First, let's scaffold an application. At the time of writing this guide, it's important to use the &lt;code&gt;--main&lt;/code&gt; flag to use the Rails 7.1 alpha version.&lt;/p&gt;

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

new rails_kamal_hetzner &lt;span class="nt"&gt;-a&lt;/span&gt; propshaft &lt;span class="nt"&gt;--main&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; tailwind &lt;span class="nt"&gt;-j&lt;/span&gt; esbuild
&lt;span class="nb"&gt;cd &lt;/span&gt;rails_kamal_hetzner
bundle add tailwindcss-rails
bin/rails tailwindcss:install
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"rails new"&lt;/span&gt;
rails g scaffold post title:string content:text
rails db:create db:migrate


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

&lt;/div&gt;

&lt;p&gt;Next, you'll need to update your routes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;# config/routes.rb
&lt;span class="gd"&gt;-  # root "articles#index"
&lt;/span&gt;&lt;span class="gi"&gt;+  root "posts#index"
&lt;/span&gt;&lt;span class="err"&gt;

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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Create a VPS on Hetzner
&lt;/h2&gt;

&lt;p&gt;Now that we have a basic app set up, let's create a VPS on &lt;a href="https://hetzner.cloud/?ref=gyPLk7XJthjg" rel="noopener noreferrer"&gt;Hetzner&lt;/a&gt;. You'll need to navigate through the sign-up and confirmation process, after which you can create a new project from your account.&lt;/p&gt;

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

&lt;p&gt;For this tutorial, we'll select the CAX11, one of the most affordable VPS options with 2vCPU and 4GB RAM.&lt;/p&gt;

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

&lt;p&gt;Please note that at the time of writing, KAMAL does not support IPv6, so you need to retain IPv4. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll also need to add an SSH key to your server.&lt;/strong&gt; Here's how to copy and paste the key:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pbcopy &amp;lt; ~/.ssh/id_rsa.pub


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

&lt;/div&gt;

&lt;p&gt;Then test your SSH access to the server with this command:&lt;/p&gt;

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

ssh root@your_server_ip


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

&lt;/div&gt;

&lt;p&gt;If you encounter the prompt, "Are you sure you want to continue connecting (yes/no/[fingerprint])?", answer 'yes'. &lt;/p&gt;

&lt;p&gt;If you're unable to SSH into the server, you'll need to resolve this issue before proceeding further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying with KAMAL
&lt;/h2&gt;

&lt;p&gt;With our application and server ready, it's time to put KAMAL into action. First, install it with the following command:&lt;/p&gt;

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

gem &lt;span class="nb"&gt;install &lt;/span&gt;kamal


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

&lt;/div&gt;

&lt;p&gt;Then run &lt;code&gt;kamal init&lt;/code&gt;. This will create several files, including &lt;code&gt;config/deploy.yml&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;.env&lt;/code&gt; file, update the &lt;code&gt;RAILS_MASTER_KEY&lt;/code&gt; value and the &lt;code&gt;KAMAL_REGISTRY_PASSWORD&lt;/code&gt; with a key created in your Docker account.&lt;/p&gt;

&lt;p&gt;Next, update the &lt;code&gt;config/deploy.yml&lt;/code&gt; file as follows:&lt;/p&gt;

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

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rails_hetzner_kamal&lt;/span&gt;

&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;adrienpoly/rails_hetzner_kamal&lt;/span&gt;

&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;hetzner_ip_v4&lt;/span&gt;

&lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;adrienpoly&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;KAMAL_REGISTRY_PASSWORD&lt;/span&gt;
&lt;span class="s"&gt;env&lt;/span&gt;

&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RAILS_MASTER_KEY&lt;/span&gt;
&lt;span class="na"&gt;ssh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt; &lt;span class="c1"&gt;# important to change it here as by default Kamal use app and Hetzner root&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can omit the other files for now. Commit your changes and then run the command to bootstrap servers with curl and Docker.&lt;/p&gt;

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

kamal server bootstrap


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

&lt;/div&gt;

&lt;p&gt;Once this operation is successful, you can execute your first deploy with &lt;code&gt;kamal deploy&lt;/code&gt;. The first deployment might take a few minutes and should conclude with a successful health check message.&lt;/p&gt;

&lt;p&gt;At this point, you should be able to visit the IP address in a browser and see your Rails app! Et voilà!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Persisting the Data
&lt;/h2&gt;

&lt;p&gt;Well well well, not really voilà yet. If you create a &lt;code&gt;Post&lt;/code&gt; and make a new deployment, you'll notice that the data is lost. This happens because the SQLite database is running inside the Docker image by default. Each time a new container is built, it erases the data.&lt;/p&gt;

&lt;p&gt;To solve this, you need to add a volume to the Docker container. In the &lt;code&gt;config/deploy.yml&lt;/code&gt; file, add this line:&lt;/p&gt;

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

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;storage:/rails/storage"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, the data is written outside of the container and persists across deploys.&lt;/p&gt;

&lt;p&gt;And that's it! You've deployed your first Rails application with KAMAL on a &lt;a href="https://hetzner.cloud/?ref=gyPLk7XJthjg" rel="noopener noreferrer"&gt;Hetzner&lt;/a&gt; VPS. &lt;/p&gt;

&lt;p&gt;Happy deploying!&lt;/p&gt;

&lt;p&gt;[15-11-2023] Updated to reflect the name change from MRSK to Kamal&lt;/p&gt;

&lt;p&gt;PS : Here is my referral link if you want to test Hetzner &lt;a href="https://hetzner.cloud/?ref=gyPLk7XJthjg" rel="noopener noreferrer"&gt;https://hetzner.cloud/?ref=gyPLk7XJthjg&lt;/a&gt; it gives you a 20€ credit to test&lt;/p&gt;

</description>
      <category>rails</category>
      <category>kamal</category>
      <category>hetzner</category>
    </item>
    <item>
      <title>StimulusJS 2.0 silencing depreciation message</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Sun, 06 Dec 2020 21:54:05 +0000</pubDate>
      <link>https://dev.to/adrienpoly/stimulusjs-2-0-silencing-depreciation-message-egn</link>
      <guid>https://dev.to/adrienpoly/stimulusjs-2-0-silencing-depreciation-message-egn</guid>
      <description>&lt;h2&gt;
  
  
  Stimulus 2.0
&lt;/h2&gt;

&lt;p&gt;🚀 The long expected &lt;a href="https://github.com/stimulusjs/stimulus/releases/tag/v2.0.0"&gt;Stimulus 2.0 is Out&lt;/a&gt;. The upgrade from 1.1.1 to 2.0 should be very smooth as they are very minimal breaking changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mute the data-target depreciation message in production
&lt;/h2&gt;

&lt;p&gt;The data-target API has changed. While the 1.1 version is still supported. There is a warning message in the console every time an old syntax is seen for the first time.&lt;/p&gt;

&lt;p&gt;The best way to fix this of course is to update all data targets but in a large code base this can take some time.&lt;/p&gt;

&lt;p&gt;Another solution to gradually update your code is to silence the warning in production.&lt;/p&gt;

&lt;p&gt;Here is a snippet to help&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stimulus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;definitionsFromContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stimulus/webpack-helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// remove Stimulus depreciation warnings in production&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>stimulus</category>
      <category>rails</category>
    </item>
    <item>
      <title>Introducing Stimulus-use composable behaviors for your controllers</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Tue, 19 May 2020 16:51:38 +0000</pubDate>
      <link>https://dev.to/adrienpoly/introducing-stimulus-use-composable-behaviors-for-your-controllers-mlc</link>
      <guid>https://dev.to/adrienpoly/introducing-stimulus-use-composable-behaviors-for-your-controllers-mlc</guid>
      <description>&lt;p&gt;TL;DR : it is not React hooks for Stimulus, just a simple way to add new behaviors and lifecycle methods to your controllers.&lt;/p&gt;

&lt;p&gt;From the early days of Stimulus, I enjoyed the simplicity and elegance of this modest framework. Nice conventions, simple and flexible API and not the least &lt;strong&gt;very robust&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivations
&lt;/h2&gt;

&lt;p&gt;In the past I explored several ways to create standard controllers either wrappers of libraries &lt;a href="https://github.com/adrienpoly/stimulus-flatpickr"&gt;stimulus-flatpickr&lt;/a&gt; or &lt;a href="https://github.com/adrienpoly/stimulus-conductor"&gt;stimulus-conductor&lt;/a&gt;. While the first got a bit of traction mostly due to the popularity of Flatpickr, very few standard Stimulus controllers really stand out from the crowd. &lt;/p&gt;

&lt;p&gt;I spent some time recently doing quite a bit of React and got to discover the hooks and among them the &lt;a href="https://github.com/streamich/react-use"&gt;react-use library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While in no way I ambition to bring full-blown hooks to Stimulus, I think there is a sweet spot for having composable modules that can enhance with new behaviors your controllers.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Stimulus-use
&lt;/h2&gt;

&lt;p&gt;So with this in mind, I imagined &lt;a href="https://github.com/stimulus-use/stimulus-use"&gt;Stimulus-use&lt;/a&gt;. For now, it is a modest set of new behaviors (your can think of lifecycle events too) that you can add to your controller. For this initial release, it adds only a few behaviors but the objective was to get it out, show it, get it tested and get feedbacks on the overall API. &lt;/p&gt;

&lt;h2&gt;
  
  
  Extend or Compose
&lt;/h2&gt;

&lt;p&gt;All new behavior are available either as a &lt;code&gt;Controller&lt;/code&gt; that you can extend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IntersectionController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stimulus-use&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;IntersectionController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;appear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// triggered when the element appears within the viewport&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or as &lt;code&gt;useFunction&lt;/code&gt; you can use when you want to enhance your controller with a new behavior or compose several new ones into a single Controller.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stimulus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useIntersection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useResize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stimulus-use&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;useIntersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;useResize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;appear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// triggered when the element appears within the viewport&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;resized&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// trigered when the element is resized&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Future &amp;amp; vision
&lt;/h2&gt;

&lt;p&gt;While I don't think all behaviors available in React-use would make sens in Stimulus, quite a few are interesting and can be ported in a Stimulus way to this project. Things like idle, visible, windowResize, clipboard, lazyImage, localStorage, animations, clipboard etc.&lt;/p&gt;

&lt;p&gt;While things tends to move slowly within Stimulus core (and I don't think it is a real issue as long as the list of issues remains close to nil) and as more and more people are getting into Stimulus we see definitely a need for more examples and standard patterns. &lt;br&gt;
Some great projects such as :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="//www.betterstimulus.com"&gt;BetterStimulus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.stimulusreflex.com"&gt;StimulusReflex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gorails.com/series/stimulus-js"&gt;all of the free screencast on GoRails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/skatkov/awesome-stimulusjs"&gt;StimulusAwesome&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;are really helping&lt;/p&gt;

&lt;p&gt;I hope this project can bring together more contributors so that we can all create in a more agile way some enhancement to Stimulus that would be :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard, (stop reinventing the wheel)&lt;/li&gt;
&lt;li&gt;Battle tested&lt;/li&gt;
&lt;li&gt;Polyfilled&lt;/li&gt;
&lt;li&gt;Documented&lt;/li&gt;
&lt;li&gt;easy to use and compose with existing code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All contributions/contributors are welcome just ping me here or on the issues/PR &lt;a href="https://github.com/stimulus-use/stimulus-use"&gt;Stimulus-use&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/stimulus-use"&gt;
        stimulus-use
      &lt;/a&gt; / &lt;a href="https://github.com/stimulus-use/stimulus-use"&gt;
        stimulus-use
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A collection of composable behaviors for your Stimulus Controllers
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/stimulus-use/stimulus-usedocs/assets/stimulus-use-logo.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Fvlg1yI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/stimulus-use/stimulus-usedocs/assets/stimulus-use-logo.png" width="500"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;&lt;strong&gt;A collection of composable behaviors for your Stimulus Controllers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://npmjs.com/package/stimulus-use" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/7ddc739b3f2eff786cba9ff2e2d78284c31aa037c451dc2776c3e9fbafe9199e/68747470733a2f2f62616467656e2e6e65742f6e706d2f762f7374696d756c75732d757365" alt="npm version"&gt;&lt;/a&gt;
&lt;a href="https://bundlephobia.com/result?p=stimulus-use" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bf0827d21c790223e0d6f5f5e467de0098164f91a00cf2aaf1abbe35df6a3e2a/68747470733a2f2f62616467656e2e6e65742f62756e646c6570686f6269612f6d696e7a69702f7374696d756c75732d757365" alt="minified + gzip size"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f47f82ebfe07a1b6f055bb2fa05788feec32d1e650803f3d6d7e028645f88b72/68747470733a2f2f62616467656e2e6e65742f6e706d2f74797065732f74736c6962"&gt;&lt;img src="https://camo.githubusercontent.com/f47f82ebfe07a1b6f055bb2fa05788feec32d1e650803f3d6d7e028645f88b72/68747470733a2f2f62616467656e2e6e65742f6e706d2f74797065732f74736c6962" alt="types included"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/065365db6530bdae540c38f04a5812777e184622628d448f26cd3765b2f1acf2/68747470733a2f2f62616467656e2e6e65742f6e706d2f6c6963656e73652f7374696d756c75732d757365"&gt;&lt;img src="https://camo.githubusercontent.com/065365db6530bdae540c38f04a5812777e184622628d448f26cd3765b2f1acf2/68747470733a2f2f62616467656e2e6e65742f6e706d2f6c6963656e73652f7374696d756c75732d757365" alt="license"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/stimulus-use/stimulus-use./docs/assets/example-buildstatus-badge.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n2nNXa13--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/stimulus-use/stimulus-use./docs/assets/example-buildstatus-badge.png" alt="Sauce test status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/stimulus-use/stimulus-use./docs/assets/stimulus-use%20example.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pthJ-uFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/stimulus-use/stimulus-use./docs/assets/stimulus-use%2520example.png" alt="Stimulus Use Example"&gt;&lt;/a&gt;
&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New lifecycle behaviors&lt;/strong&gt;: adds new standard behaviors to your Stimulus controllers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable&lt;/strong&gt;: compose at will different behaviors in a single controller with mixins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular&lt;/strong&gt;: built as ES6 modules, just import what you need and tree shaking will remove the rest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typescript&lt;/strong&gt;: Types available, better autocompletion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tiny&lt;/strong&gt;: 3k gzip + tree shaking 🌳🌳🌳&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
Getting Started&lt;/h2&gt;

&lt;h3&gt;
Stimulus 3&lt;/h3&gt;

&lt;p&gt;If you want to use &lt;code&gt;stimulus-use&lt;/code&gt; with Stimulus 3 you can use the version &lt;code&gt;0.50.0+&lt;/code&gt;. This and all future versions are designed to work with the &lt;code&gt;@hotwired/stimulus&lt;/code&gt; npm package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If other packages still depend on the &lt;code&gt;stimulus&lt;/code&gt; npm package you can safely keep that in your &lt;code&gt;package.json&lt;/code&gt;, this won't break the &lt;code&gt;stimulus-use&lt;/code&gt; compability.&lt;/p&gt;

&lt;h4&gt;
Using npm&lt;/h4&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm i stimulus-use @hotwired/stimulus&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
Using yarn&lt;/h4&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn add stimulus-use @hotwired/stimulus&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
Stimulus 2 and below&lt;/h3&gt;

&lt;p&gt;If you want to use &lt;code&gt;stimulus-use&lt;/code&gt; with Stimulus…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/stimulus-use/stimulus-use"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>stimulus</category>
      <category>turbolinks</category>
      <category>rails</category>
    </item>
    <item>
      <title>Animations with Turbolinks and Stimulus</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Wed, 13 May 2020 03:26:31 +0000</pubDate>
      <link>https://dev.to/adrienpoly/animations-with-turbolinks-and-stimulus-4862</link>
      <guid>https://dev.to/adrienpoly/animations-with-turbolinks-and-stimulus-4862</guid>
      <description>&lt;p&gt;When using CSS animations with Turbolinks, you may experience page blink during page load. We will see how we can easily change that using the life cycle events of a Stimulus controller.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turbolinks preview
&lt;/h2&gt;

&lt;p&gt;When navigating back, Turbolinks will first display a preview of the page that was stored in the local cache and then replace this preview by the server response. This give the instant page load feeling effect of Turbolinks.&lt;/p&gt;

&lt;p&gt;This preview comes from a snapshot taken locally by Turbolinks during the previous visit. Two things must be considered :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The preview has the state of the animations when you left the page.&lt;/li&gt;
&lt;li&gt;If your animations are meant to start on page load then they will most probably start when the preview page is displayed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those are typically two sources of blink effect when using animations with Turbolinks.&lt;/p&gt;

&lt;p&gt;The first one because the page preview displays the page with the animations already played but then resets it when the preview is replaced by the real server response.&lt;/p&gt;

&lt;p&gt;The second because if the animations start on the page preview then once the page preview is replaced, the animation will be reset. So either the animation is played twice or partially during first load. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Lets assume a typical controller where you play an animation on an element during after page load.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;play-animation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1) Ignore preview
&lt;/h3&gt;

&lt;p&gt;Adding simple helper can tell you if you are on a preview page on not&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;isPreview&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-turbolinks-preview&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now during &lt;code&gt;connect&lt;/code&gt; we can easily know if we are in a preview or not. If we are in a preview we shouldn't play the animation as it would most likely be interrupted/play twice&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPreview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;play-animation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;isPreview&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-turbolinks-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Tear down before snapshot
&lt;/h3&gt;

&lt;p&gt;The goal is to bring back the page to its initial state before snapshot. For this we will use the &lt;code&gt;disconnect()&lt;/code&gt; function that occurs right before the Turbolinks snapshot and simply remove animations that we may have played.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;play-animation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So a typical complete solution would look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPreview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;play-animation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;play-animation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;isPreview&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-turbolinks-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy Stimulus 🦄&lt;/p&gt;

</description>
      <category>turbolinks</category>
      <category>stimulus</category>
    </item>
    <item>
      <title>Dynamic module import with Stimulus JS</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Mon, 11 May 2020 21:12:32 +0000</pubDate>
      <link>https://dev.to/adrienpoly/dynamic-module-import-with-stimulus-js-297g</link>
      <guid>https://dev.to/adrienpoly/dynamic-module-import-with-stimulus-js-297g</guid>
      <description>&lt;h3&gt;
  
  
  Scoped behavior by default
&lt;/h3&gt;

&lt;p&gt;Being built on top of the mutation observer, Stimulus Controllers are only loaded once a &lt;code&gt;data-controller="my-controller"&lt;/code&gt; is visible within the DOM. &lt;/p&gt;

&lt;p&gt;This is a great way to scope JS behavior to an element within a page.&lt;/p&gt;

&lt;p&gt;With the typical Webpack loader, all the Controllers are bundled within the pack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;definitionsFromContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stimulus/webpack-helpers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./controllers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;js$/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;definitionsFromContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Importing large ES modules
&lt;/h3&gt;

&lt;p&gt;When importing very large JS library you might want to only load them only on pages where the controller is used to avoid loading too much JS on other pages.&lt;/p&gt;

&lt;p&gt;One nice feature of Webpack is the ability to dynamically load modules.&lt;/p&gt;

&lt;p&gt;Using the lifecycle of Stimulus Controllers you can stick you dynamic import right into the &lt;code&gt;initialize()&lt;/code&gt; or &lt;code&gt;connect()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Here is and example to dynamically load &lt;code&gt;moment&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stimulus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatedTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dddd, MMMM Do YYYY, h:mm:ss a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a working demo&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/stimulus-dynamic-import-z7coy"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>stimulus</category>
      <category>webpack</category>
    </item>
    <item>
      <title>A praise to Microbundle</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Sun, 10 May 2020 13:02:43 +0000</pubDate>
      <link>https://dev.to/adrienpoly/a-praise-to-microbundle-1dej</link>
      <guid>https://dev.to/adrienpoly/a-praise-to-microbundle-1dej</guid>
      <description>&lt;p&gt;Microbundle is a zero-configuration bundler for tiny modules, powered by Rollup and created by Jason Miller  the inventor of Preact.&lt;/p&gt;

&lt;p&gt;I tested it in the past on a few projects and was always impressed by the ease of use and the performances. Out of all bundlers I tested, Microbundle has always been the one delivering the smallest builds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/developit/microbundle/releases/tag/0.12.0"&gt;Microbunlde v0.12 was released few days ago&lt;/a&gt; this was a good opportunity to test it again and I have to say that I am SOLD !!!&lt;/p&gt;

&lt;p&gt;I am working on a typescript library project. My bundler was a mix of Typscript transpiller, Babel and Rollup. Lots of settings I had no clue about and lots of time spent trying to tune it. &lt;/p&gt;

&lt;p&gt;I switch to Microbundle and it: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Worked out of the box&lt;/li&gt;
&lt;li&gt;Removed at least 10 packages from my &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Reduced the build size by 2&lt;/li&gt;
&lt;li&gt;Delivers out of the box &lt;code&gt;umd&lt;/code&gt;, &lt;code&gt;CommonJS/Node&lt;/code&gt;, &lt;code&gt;types&lt;/code&gt; and &lt;code&gt;module&lt;/code&gt; builds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🙏 🙏 Thanks Jason &amp;amp; team 👏👏&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__8773"&gt;
    &lt;a href="/_developit" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NTCmCfc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F8773%252FLljqR8gE.jpg" alt="_developit image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/_developit"&gt;Jason Miller 🦊⚛&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/_developit"&gt;&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>bundler</category>
    </item>
    <item>
      <title>Composable Stimulus Controllers?</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Sat, 09 May 2020 22:16:33 +0000</pubDate>
      <link>https://dev.to/adrienpoly/composable-stimulus-controllers-2i9h</link>
      <guid>https://dev.to/adrienpoly/composable-stimulus-controllers-2i9h</guid>
      <description>&lt;p&gt;Quite some time ago I wrote a simple Stimulus wrapper for &lt;a href="https://github.com/adrienpoly/stimulus-flatpickr"&gt;Flatpickr&lt;/a&gt;. I learned a lot while doing this project. One of my initial goal was  to explore the possibility of having standard controllers with in the Stimulus world. Controllers anyone could use to avoid reinventing the wheel every time.&lt;/p&gt;

&lt;p&gt;Stimulus by default is a modest (yet powerful) framework. &lt;a href="https://github.com/skatkov/awesome-stimulusjs"&gt;The list of available  standard controllers&lt;/a&gt; is also rather modest. &lt;/p&gt;

&lt;p&gt;Beside a few exceptions I don't have the feeling they are widely used. While many factors can explain it, for me the missing ability to compose multiple simple behavior within a controller has been a major obstacle of adoption.&lt;/p&gt;

&lt;p&gt;I have been recently looking into this and made a few prototypes. Would love to have feedbacks if anyone already tackled this problem&lt;/p&gt;

&lt;h2&gt;
  
  
  Have you made in your projects some reusable, shareable and composable Controllers ?
&lt;/h2&gt;

</description>
      <category>stimulus</category>
      <category>rails</category>
    </item>
    <item>
      <title>Hey.com / New front end paradigm / What is DHH cooking?</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Mon, 10 Feb 2020 16:23:00 +0000</pubDate>
      <link>https://dev.to/adrienpoly/hey-com-new-front-end-paradigm-what-is-dhh-cooking-1gkp</link>
      <guid>https://dev.to/adrienpoly/hey-com-new-front-end-paradigm-what-is-dhh-cooking-1gkp</guid>
      <description>&lt;p&gt;DHH announced last week a very promising new email service from Basecamp&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1225487645268160512-857" src="https://platform.twitter.com/embed/Tweet.html?id=1225487645268160512"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1225487645268160512-857');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1225487645268160512&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Earlier DHH mentioned some new technics for optimizing front end (simpler code/faster)&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1212930897357479937-971" src="https://platform.twitter.com/embed/Tweet.html?id=1212930897357479937"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1212930897357479937-971');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1212930897357479937&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Hey.com is built using this new approach and DHH will present it at Rails conf.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1225504208465670147-604" src="https://platform.twitter.com/embed/Tweet.html?id=1225504208465670147"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1225504208465670147-604');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1225504208465670147&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;What are your guesses?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>rails</category>
      <category>turbolinks</category>
      <category>stimulus</category>
    </item>
    <item>
      <title>Critical CSS with Rails and Webpacker - SprocketsLess Part 1</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Mon, 02 Sep 2019 20:09:26 +0000</pubDate>
      <link>https://dev.to/adrienpoly/critical-css-with-rails-and-webpacker-sprocketsless-part-1-2bck</link>
      <guid>https://dev.to/adrienpoly/critical-css-with-rails-and-webpacker-sprocketsless-part-1-2bck</guid>
      <description>&lt;p&gt;This is the first of hopefully a series of articles on new advanced usage available when moving all assets to Webpacker. In the first part, we will look into optimizing your CSS size.&lt;/p&gt;

&lt;p&gt;We all want fast &amp;amp; reliable web pages. When doing a &lt;a href="https://developers.google.com/speed/pagespeed/insights/?hl=en"&gt;Page Speed Audit&lt;/a&gt; what often comes up as a recommendation is &lt;strong&gt;critical CSS&lt;/strong&gt;. Critical CSS and especially above the fold critical CSS is the ability to inline (in the HTML) the minimal CSS required to render the top of your page (above the fold). I have for some time looked into an easy solution to achieve this in a Rails app but I was never really successful at it.&lt;/p&gt;

&lt;p&gt;One of the great thing with Webpack (ie Webpacker in Rails) is all of the echo systems around it. While the JS side in Rails is largely documented they are also lots of tools available for CSS &amp;amp; images.&lt;/p&gt;

&lt;p&gt;A few months ago I discovered a great video from &lt;a href="https://gorails.com/"&gt;GoRails&lt;/a&gt; for using &lt;a href="https://gorails.com/episodes/purgecss"&gt;PurgeCss in a Rails application&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding PurgeCSS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q-X3Lyoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4anqgftf0j9v8zih0mh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q-X3Lyoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4anqgftf0j9v8zih0mh5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The global concept of PurgeCSS is that on one side you feed PurgeCSS with all of your files where you would have some CSS class used (usually &lt;code&gt;.html&lt;/code&gt;, &lt;code&gt;html.erb&lt;/code&gt;, &lt;code&gt;.js&lt;/code&gt;). PurgesCSS create a list of all token that could be CSS selectors. &lt;/p&gt;

&lt;p&gt;On the other side Webpacker create a CSS bundle using the &lt;code&gt;mini-css-extract-plugin&lt;/code&gt;. PurgeCSS extract a list of tokens&lt;/p&gt;

&lt;p&gt;The result is the intersection of those two lists of tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple Pack with Multiple Rules
&lt;/h2&gt;

&lt;p&gt;With Webpacker it is easy to have multiple packs. You just need to create a new &lt;code&gt;some-pack.js&lt;/code&gt; file in &lt;code&gt;app/javascript/packs&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The global idea of what we are going to do is:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define a second pack &lt;code&gt;critical.js&lt;/code&gt; with only some CSS import in it.&lt;/li&gt;
&lt;li&gt;Split our PurgesCss process in PostCss to apply much stricter rules for &lt;code&gt;critical.css&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inline our Critical CSS in the HTML as &lt;code&gt;Dev.to&lt;/code&gt; &lt;a href="https://github.com/thepracticaldev/dev.to/blob/master/app/views/layouts/_styles.html.erb"&gt;is doing by the way&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Lazy load our main &lt;code&gt;application.css&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Our critical.js entrypoint
&lt;/h4&gt;

&lt;p&gt;Given an &lt;strong&gt;application.js&lt;/strong&gt; that would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/application.js&lt;/span&gt;

&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rails/ujs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;local-time&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turbolinks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// import CSS&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheets/application.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// import Stimulus controllers&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;controllers/index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// import vendor JS&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bootstrap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our main entry point, &lt;strong&gt;import&lt;/strong&gt; our main &lt;strong&gt;application.scss&lt;/strong&gt; that usually look something like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/stylesheets/application.scss&lt;/span&gt;

&lt;span class="c1"&gt;// Fonts&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"config/fonts"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Graphical variables&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"config/colors"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Vendor&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"~bootstrap/scss/functions"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"config/bootstrap_variables"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"~bootstrap/scss/bootstrap"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$fa-font-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"~@fortawesome/fontawesome-free/webfonts"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"~@fortawesome/fontawesome-free/scss/fontawesome"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"~@fortawesome/fontawesome-free/scss/brands"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Components&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"components/index"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// layouts&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"layouts/sticky-footer"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can create a very basic &lt;code&gt;critical.js&lt;/code&gt;, the only thing it will do is to import a new critical.scss stylesheet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/javascript/packs/critical.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheets/critical.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In our &lt;strong&gt;&lt;code&gt;critical.scss&lt;/code&gt;&lt;/strong&gt; file we can start to be a little more selective as what we put inside to help PurgeCSS make a better job. (it does make a small difference)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// colors&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"config/colors"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// vendor&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"~bootstrap/scss/functions"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"config/bootstrap_variables"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"config/bootstrap_critical"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// pick only the Bootstrap module you need&lt;/span&gt;

&lt;span class="c1"&gt;// Components&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"components/banner"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//just pick the components you need for the homepage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  PostCSS / PurgeCSS configuration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Then this is the important part. We need to tell PurgeCSS to apply different rules per files. Luckily we have a context full of information in PostCSS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So we can pass our information context to the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Add a context variable to our envrionment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss-import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss-flexbugs-fixes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss-preset-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
      &lt;span class="na"&gt;autoprefixer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;flexbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-2009&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;purgeCss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Call our PurgeCss plugin with this context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;purgeCss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fullhuman/postcss-purgecss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;htmlFilePatterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;defaultExtractor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Za-z0-9-_:&lt;/span&gt;&lt;span class="se"&gt;/]&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And now that we have the filename in PurgeCss, we can specify different rules for each file. For my critical CSS, I specify only pages related to the home page and the usual set of patterns for all other files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlFilePatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;critical.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/views/pages/index.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/views/shared/_navbar.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/views/layouts/application.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/**/*.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config/initializers/simple_form_bootstrap.rb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/helpers/**/*.rb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/javascript/**/*.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So in full, it looks like that&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// postcss.config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss-import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss-flexbugs-fixes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss-preset-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
      &lt;span class="na"&gt;autoprefixer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;flexbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-2009&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;purgeCss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;purgeCss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fullhuman/postcss-purgecss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;htmlFilePatterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;defaultExtractor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Za-z0-9-_:&lt;/span&gt;&lt;span class="se"&gt;/]&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlFilePatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;critical.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/views/pages/index.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/views/shared/_navbar.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/views/layouts/application.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/**/*.html.erb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config/initializers/simple_form_bootstrap.rb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/helpers/**/*.rb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/javascript/**/*.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;In a small test I did I had those results&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial bundle size of 32kb&lt;/li&gt;
&lt;li&gt;With purge CSS this dropped to 9kb&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;My critical.css only 3kb!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BAMMMMM 🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉 &lt;/p&gt;

&lt;h2&gt;
  
  
  Inline CSS from Webpacker
&lt;/h2&gt;

&lt;p&gt;I did scratch my head a bit to inline my CSS file in the HTML. Thanks to &lt;a href="https://stackoverflow.com/questions/57663867/how-to-inline-css-in-rails-header-with-webpacker-assets"&gt;Stackoverflow&lt;/a&gt; I could get some help here&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_page?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Inline the critical CSS --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'public'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Webpacker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'critical.css'&lt;/span&gt;&lt;span class="p"&gt;))).&lt;/span&gt;&lt;span class="nf"&gt;html_safe&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Lazy load the rest with loadCSS --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="no"&gt;Webpacker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'application.css'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"style"&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"this.rel='stylesheet'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="no"&gt;Webpacker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'application.css'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;stylesheet_pack_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Et voila!!!!
&lt;/h2&gt;

&lt;p&gt;Demo: &lt;a href="https://sprockets-less-rails6.herokuapp.com"&gt;https://sprockets-less-rails6.herokuapp.com&lt;/a&gt;&lt;br&gt;
Source code: &lt;a href="https://github.com/adrienpoly/sprockets-less-rails6"&gt;https://github.com/adrienpoly/sprockets-less-rails6&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>webpacker</category>
      <category>criticalcss</category>
      <category>sprocketsless</category>
    </item>
    <item>
      <title>Rails 6.0.0 beta1 released</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Sat, 19 Jan 2019 10:21:04 +0000</pubDate>
      <link>https://dev.to/adrienpoly/rails-600-beta1-released-43c</link>
      <guid>https://dev.to/adrienpoly/rails-600-beta1-released-43c</guid>
      <description>&lt;p&gt;Hey &lt;/p&gt;

&lt;p&gt;Rails 6.0.0 beta1 has just been released 🎉 🚀.&lt;/p&gt;

&lt;p&gt;TL;DR&lt;/p&gt;

&lt;h2&gt;
  
  
  Webpacker
&lt;/h2&gt;

&lt;p&gt;Webpack is now the official JS bundler, Sprockets remains the recommended asset pipeline for static assets (images) and CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Frameworks
&lt;/h2&gt;

&lt;p&gt;It includes 2 new frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Action Text : to easily add rich content support to your app&lt;/li&gt;
&lt;li&gt;Action MailBox : to easily route incoming emails&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Even more scalable
&lt;/h2&gt;

&lt;p&gt;2 major features for scaling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parallel testing: speeds up your testing suite in multicores environment&lt;/li&gt;
&lt;li&gt;Multiple database: Simple API to support multiple database with Active Records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and lots of other improvements&lt;/p&gt;

&lt;h2&gt;
  
  
  The complete release note
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://weblog.rubyonrails.org/2019/1/18/Rails-6-0-Action-Mailbox-Action-Text-Multiple-DBs-Parallel-Testing/"&gt;https://weblog.rubyonrails.org/2019/1/18/Rails-6-0-Action-Mailbox-Action-Text-Multiple-DBs-Parallel-Testing/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>news</category>
    </item>
    <item>
      <title>Step by Step guide to test Rails ActiveText</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Thu, 04 Oct 2018 13:34:13 +0000</pubDate>
      <link>https://dev.to/adrienpoly/step-by-step-guide-to-test-rails-activetext-4b8o</link>
      <guid>https://dev.to/adrienpoly/step-by-step-guide-to-test-rails-activetext-4b8o</guid>
      <description>&lt;h2&gt;
  
  
  🚧❌ EDITED ActionText is now fully released in Rails 6 don't follow this guide that was written for the preview version
&lt;/h2&gt;

&lt;p&gt;You might have seen the video of DHH about ActionText upcoming feature in Rails 6. This is a step by step guide for creating the exact same example as in the video.&lt;/p&gt;

&lt;p&gt;⚠️ If like me you never ran an edge version of Rails before and wonder how to do it then this is for you&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a new app from the Edge version of Rails
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Clone the Rails repo
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/rails/rails.git
&lt;span class="nb"&gt;cd &lt;/span&gt;rails
bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a new app with Rails Edge, YABE (YABE: Yet Another Blog Example)
&lt;/h3&gt;

&lt;p&gt;We will want to create a new app within the same directory and using the locally installed Rails generator&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#move out of rails folder first&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..

&lt;span class="c"&gt;#create the app with the local rails generator and the edge flag to use GH master branch&lt;/span&gt;
rails/railties/exe/rails new yabe &lt;span class="nt"&gt;--edge&lt;/span&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;yabe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start the app
&lt;/h3&gt;

&lt;p&gt;⚠️ remember to always use the local rails command: &lt;code&gt;bin/rails&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/rails s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should now have the rails startup screen showing &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rails version: 6.0.0.alpha&lt;/strong&gt; 🎉🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing ActionText
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add the ActionText gem (and image variants for active Storage):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"actiontext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;github: &lt;/span&gt;&lt;span class="s2"&gt;"rails/actiontext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="s2"&gt;"action_text"&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"image_processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.2"&lt;/span&gt; &lt;span class="c1"&gt;# for Active Storage variants&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install gem, assets, npm dependency, and migrations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle install
bin/rails action_text:install
bin/rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scaffold Post
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/rails g scaffold post title:string
bin/rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add a rich text field to Post
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/post.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_rich_text&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Active Text brings a polymorphic model under the hood for managing &lt;code&gt;RichText&lt;/code&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Add a field to your form
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&amp;lt;%= form.rich_text_area :content %&amp;gt;&lt;/strong&gt; : rich_text_area is the new content type to display Trix&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;%#app/views/posts/_form.html.erb %&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  …
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rich_text_area&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  …
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  finally, display the rich text on a page:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update the strong params in PostsController
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_params&lt;/span&gt;
  &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:post&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start blogging
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My 2 cents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;My first take out was to use an edge version of Rails.&lt;/li&gt;
&lt;li&gt;With regards to ActiveText I am impressed with how simple it is to now add rich text editing in a Rails app. &lt;/li&gt;
&lt;li&gt;I love Trix don't get me wrong but I would like to have a layer of abstraction to potentially have other front-end solution for the Editor.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>actiontext</category>
      <category>trix</category>
      <category>guide</category>
    </item>
    <item>
      <title>Introducing Stimulus-Flatpickr wrapper 📅</title>
      <dc:creator>Adrien Poly</dc:creator>
      <pubDate>Wed, 12 Sep 2018 12:30:46 +0000</pubDate>
      <link>https://dev.to/adrienpoly/introducing-stimulus-flatpickr-wrapper--5c23</link>
      <guid>https://dev.to/adrienpoly/introducing-stimulus-flatpickr-wrapper--5c23</guid>
      <description>&lt;p&gt;I really enjoyed using &lt;a href="https://stimulusjs.org/" rel="noopener noreferrer"&gt;Stimulus JS&lt;/a&gt; since it has been released early this year. For once I can now easily organize my JS code without pulling a full-blown frontend framework.&lt;/p&gt;

&lt;p&gt;Stimulus-flatpickr wrapper started as an experiment, I needed to use Flatpickr in a project and built a Stimulus Controller for it. I quickly realized that it could make sense to have a generic Stimulus controller for this library.&lt;/p&gt;

&lt;p&gt;Today we will demonstrate this package through a simple, yet interesting example. I have worked quite a bit recently with date pickers and realized that it is always very simple to convert a field to a date pickers but they are many small details required to make it a real easy to use solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is to create a basic booking system where the user:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;can only select available dates (the ones already booked must be disabled)&lt;/li&gt;
&lt;li&gt;gets a datepicker in his language&lt;/li&gt;
&lt;li&gt;see a date in the input field in the locale format&lt;/li&gt;
&lt;li&gt;see a list of all bookings&lt;/li&gt;
&lt;li&gt;all of this playing nicely in a Single Page Application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the stack is rather simple: Rails, Stimulus, Turbolinks, and Flatpickr for the date picking solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the end we won't have any Ajax at all and less than 10 lines of Javascript to do this 🎉🎉🎉&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets get started: New app and stimulus setup
&lt;/h2&gt;

&lt;p&gt;They are several tutorials out there, I won't get into all the details but settings up Stimulus in your Rails app if you already have webpack installed is as simple as that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails webpacker:install:stimulus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add Stimulus package to your &lt;code&gt;package.json&lt;/code&gt;, adds the initialization code in your main &lt;code&gt;application.js&lt;/code&gt; file and a new controllers directory under javascript for all of your new &lt;code&gt;Stimulus&lt;/code&gt; controllers&lt;/p&gt;

&lt;p&gt;You can read this article for more details about &lt;a href="https://medium.com/cedarcode/installing-stimulus-js-in-a-rails-app-c8564ba51ea2" rel="noopener noreferrer"&gt;setting up Stimulus in your rails&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For today's demo, we are going to create a brand new app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  rails new &lt;span class="nt"&gt;--webpack&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;stimulus stimulus-flatpickr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...and don't forget to add the packs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;  #app/views/layouts/application.html.erb
  ...
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;stylesheet_pack_tag&lt;/span&gt;    &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;media: &lt;/span&gt;&lt;span class="s1"&gt;'all'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_pack_tag&lt;/span&gt; &lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-turbolinks-track'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reload'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Appointment Model and Controller
&lt;/h2&gt;

&lt;p&gt;We are doing a booking engine. We need an Appointment model with a single column a start_at date and a &lt;code&gt;scope&lt;/code&gt; method to get the &lt;code&gt;up_comings&lt;/code&gt; appointments for the next n days (we can only book for the next 60 days).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#models/appointment.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Appointment&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:start_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:up_comings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nb_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                       &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'start_at &amp;gt;= ? AND start_at &amp;lt; ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;nb_days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;start_at: :asc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our controller is pretty standard (for simplicity we only handle the success path here 👶, no error managment)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppointmentsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_appointment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="sx"&gt;%i[update destroy]&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@appointments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;up_comings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@appointments_dates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@appointments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:start_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@appointment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;appointments_path&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appointment_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;appointments_path&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appointment_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="vi"&gt;@appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;appointments_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_appointment&lt;/span&gt;
    &lt;span class="vi"&gt;@appointment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;appointment_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:appointment&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:start_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  stimulus-flatpickr controller
&lt;/h2&gt;

&lt;p&gt;As per the &lt;a href="https://github.com/adrienpoly/stimulus-flatpickr#advanced-usage" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; we are going to create a Stimulus controller that will extend the generic stimulus-flatpickr controller.&lt;/p&gt;

&lt;p&gt;First, let's add the packages that we will need&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  yarn add stimulus-flatpickr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and add the new controller&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./controllers/flatpickr_controller.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Flatpickr&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stimulus-flatpickr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flatpickr/dist/themes/dark.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// creates a new Stimulus controller by extending stimulus-flatpickr wrapper controller&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Flatpickr&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The views
&lt;/h2&gt;

&lt;p&gt;Lets put a small structure to have the booking form on the left and the up comings appointments list on the right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;#app/views/appointments/index.html.erb
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="s2"&gt;".title"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="s2"&gt;".new"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;appointment: &lt;/span&gt;&lt;span class="vi"&gt;@appointment&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="s2"&gt;".appointments"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="vi"&gt;@appointments&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

#app/views/appointments/_appointment.html.erb
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"appointments"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;appointment: &lt;/span&gt;&lt;span class="n"&gt;appointment&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;link_to&lt;/span&gt; &lt;span class="s2"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;appointment_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;method: :delete&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;and our form where all the magic will happen 🎉&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;#app/views/appointments/_form.html.erb
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_with&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="n"&gt;appointment&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_field&lt;/span&gt; &lt;span class="ss"&gt;:start_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;data: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;controller: &lt;/span&gt;&lt;span class="s2"&gt;"flatpickr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;flatpickr_min_date: &lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;flatpickr_max_date: &lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;flatpickr_disable: &lt;/span&gt;&lt;span class="no"&gt;Appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;up_comings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:start_at&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is the important part to understand&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;We defined a &lt;code&gt;flatpickr_controller.js&lt;/code&gt; so whenever an HTML element has a &lt;code&gt;data-controller="flatpickr"&lt;/code&gt; attribute, then the stimulus controller will enter into action.&lt;/p&gt;

&lt;p&gt;So here in the view, &lt;code&gt;data: { controller: "flatpickr" }&lt;/code&gt; will be converted to &lt;code&gt;data-controller="flatpickr"&lt;/code&gt; and therefore convert the field into a datepicker.&lt;/p&gt;

&lt;p&gt;We can also pass options to the datepicker using the same data attributes(&lt;code&gt;data-flatpickr-the-kebab-case-option-name)&lt;/code&gt;. Here we set a min and max date to disable everything before today and everything after today + 60 days.&lt;/p&gt;

&lt;p&gt;Also, we prepare for the next step where we will disable the dates that are already booked by passing an array of the current bookings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Submit on select
&lt;/h2&gt;

&lt;p&gt;Lets automatically submit whenever a user selects a date (not perfect UX! I know, it is mostly for simple demo purpose).&lt;br&gt;
The flatpickr controller has all the official flatpickr hooks available (open, close, change etc). Here we need to submit the form when the value has changed. So let's override the &lt;code&gt;change()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Flatpickr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// automatically submit form when a date is selected&lt;/span&gt;
  &lt;span class="nf"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectedDates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dateStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Going Live
&lt;/h2&gt;

&lt;p&gt;At this point we have the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx73wolvxxqxovspv2cdu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx73wolvxxqxovspv2cdu.gif" alt="stimulus-flatpickr demo" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We start to have something interactive.... The cool thing is that Turbolinks being installed by default kicks in automatically and &lt;code&gt;Ajaxify&lt;/code&gt; all links. All Stimulus controllers are by designed working with Turbolinks. &lt;strong&gt;So there is nothing else to do here, it just works!&lt;/strong&gt;. No custom Ajax call or SRJ to have this SPA look and feel. 💪 🚀 ❤️&lt;/p&gt;

&lt;h2&gt;
  
  
  Localizing the date picker and the date format
&lt;/h2&gt;

&lt;p&gt;We have a SPA look &amp;amp; feel and the availabilities for our booking engine. The next step is to localize it correctly. Currently, it is only in English and the date format if rather ugly &lt;code&gt;2018-09-12&lt;/code&gt; 👎.&lt;/p&gt;

&lt;h4&gt;
  
  
  date formats
&lt;/h4&gt;

&lt;p&gt;The stimulus-flatpickr wrapper offers a nice &lt;strong&gt;bonus feature&lt;/strong&gt; over the standard library, it will convert &lt;code&gt;strftime&lt;/code&gt; date formats to flatpickr custom date formats.&lt;/p&gt;

&lt;p&gt;So to customize the date format we can pass the local format directly to the date picker like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="ss"&gt;data: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;controller: &lt;/span&gt;&lt;span class="s2"&gt;"flatpickr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;flatpickr_alt_input: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;flatpickr_alt_format: &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"date.formats.long"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;flatpickr_default_date: &lt;/span&gt;&lt;span class="n"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;flatpickr_disable: &lt;/span&gt;&lt;span class="vi"&gt;@appointments_dates&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_at&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;flatpickr_min_date: &lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;flatpickr_max_date: &lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;flatpickr_alt_format: t("date.formats.long")&lt;/code&gt; -&amp;gt; will output &lt;code&gt;"%B %d, %Y"&lt;/code&gt; when the locale is &lt;code&gt;:en&lt;/code&gt; and &lt;code&gt;"%e %B %Y"&lt;/code&gt; when the locale is &lt;code&gt;:fr&lt;/code&gt; and this gets converted automatically to the nearest flatpickr format. As DRY as it can be 🎉!&lt;/p&gt;

&lt;h4&gt;
  
  
  Translations
&lt;/h4&gt;

&lt;p&gt;We now have almost everything. The last point is to correctly translate the datepicker for every locale.&lt;/p&gt;

&lt;p&gt;We are going to import the different locales in our stimulus controller. Every time time Turbolinks silently replace the content of the page, the &lt;code&gt;initialize()&lt;/code&gt; function is of the stimulus controller is called. This is where we are going to set our local and pass it to flatpickr.&lt;/p&gt;

&lt;p&gt;Our final controller looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Flatpickr&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stimulus-flatpickr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// import a theme (could be in your main CSS entry too...)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flatpickr/dist/themes/dark.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// import the translation files and create a translation mapping&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;French&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flatpickr/dist/l10n/fr.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;english&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flatpickr/dist/l10n/default.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create a new Stimulus controller by extending stimulus-flatpickr wrapper controller&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Flatpickr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;locales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;French&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;en&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;english&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//set the locale and also sets the global flatpickr settings  &lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;altInput&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;showMonths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// automatically submit form when a date is selected&lt;/span&gt;
  &lt;span class="nf"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectedDates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dateStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  That's all folks!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi0xi1gv0keumrynau78r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi0xi1gv0keumrynau78r.gif" alt="stimulus-flatpickr demo" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the entire demo project here 👉 &lt;a href="https://github.com/adrienpoly/rails_stimulus_flatpickr" rel="noopener noreferrer"&gt;https://github.com/adrienpoly/rails_stimulus_flatpickr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;and more important&lt;/strong&gt; the stimulus-flatpickr wrapper 👉 &lt;a href="https://github.com/adrienpoly/stimulus-flatpickr" rel="noopener noreferrer"&gt;https://github.com/adrienpoly/stimulus-flatpickr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this introduction. I personally think we will see more and more standard Stimulus controllers and the Rails community will more and more drop Gems used for front end packages only. &lt;/p&gt;

&lt;p&gt;I am not senior dev with tons of experience so feel free to &lt;strong&gt;Comments, issues, PR&lt;/strong&gt;. They are all welcome and if you feel this package is useful for you, leave it a star ⭐&lt;/p&gt;

&lt;p&gt;Happy Coding 🎉&lt;/p&gt;

</description>
      <category>flatpickr</category>
      <category>stimulus</category>
      <category>rails</category>
      <category>turbolinks</category>
    </item>
  </channel>
</rss>
