<?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: AquaDrehz</title>
    <description>The latest articles on DEV Community by AquaDrehz (@aquadrehz).</description>
    <link>https://dev.to/aquadrehz</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%2F657602%2F0bb74b9c-295d-4241-b7bc-4d4299a7b060.jpeg</url>
      <title>DEV Community: AquaDrehz</title>
      <link>https://dev.to/aquadrehz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aquadrehz"/>
    <language>en</language>
    <item>
      <title>Rails 7.0 demo with Hotwire and Tailwind</title>
      <dc:creator>AquaDrehz</dc:creator>
      <pubDate>Fri, 07 Jan 2022 07:39:44 +0000</pubDate>
      <link>https://dev.to/aquadrehz/rails-70-demo-with-hotwire-and-tailwind-4b3d</link>
      <guid>https://dev.to/aquadrehz/rails-70-demo-with-hotwire-and-tailwind-4b3d</guid>
      <description>&lt;p&gt;A new Rails was released before  2022. This release makes Rails stand out from another framework significantly by getting rid of the most painful issue by &lt;a href="https://world.hey.com/dhh/modern-web-apps-without-javascript-bundling-or-transpiling-a20f2755" rel="noopener noreferrer"&gt;replacing NodeJS with Hotwire as a default UI/UX&lt;/a&gt;. But still, allow accessing NodeJS with Import map for additional approach.&lt;/p&gt;

&lt;p&gt;This article would explain an implementation step-by-step so you can compare it to Rails 6 app more preciously&lt;/p&gt;

&lt;p&gt;In this demo, I've forked the original one which uses the important component like the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hotwired.dev/" rel="noopener noreferrer"&gt;Hotwire&lt;/a&gt; - as UI/UX and JavaScript framework (default)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; - as CSS framework&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://edgeguides.rubyonrails.org/action_text_overview.html#installation" rel="noopener noreferrer"&gt;ActionText&lt;/a&gt; - as rich text content for text box&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pre-requisite
&lt;/h3&gt;

&lt;p&gt;Recommended version&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;rvm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.29.12&lt;/span&gt;
&lt;span class="na"&gt;ruby&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.3&lt;/span&gt;
&lt;span class="na"&gt;rails&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;7.0.0&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  1) Initial app project
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new app named 'blog'
```ssh
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;rails new blog --css tailwind&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
- Generate scaffold of the blog post
```ssh


rails g scaffold post title


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Install ActionText
```ssh
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;rails action_text:install&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
- Migrate Rails DB
```ssh


rails db:create db:migrate


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  2) Add Rich Text area
&lt;/h3&gt;

&lt;p&gt;Add content: as Rich Text Area from ActionText to Model, View, and Controller&lt;br&gt;
All html.erb files were included classes that will be used by Tailwind CSS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model - Posts
```ruby
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  app/models/post.rb
&lt;/h1&gt;

&lt;p&gt;class Post &amp;lt; ApplicationRecord&lt;br&gt;
  validates :title, presence: true&lt;/p&gt;

&lt;p&gt;has_rich_text :content&lt;br&gt;
end&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- View - Posts Templates
```erb


&amp;lt;!-- app/views/posts/_form.html.erb --&amp;gt;
&amp;lt;!-- ... --&amp;gt;
&amp;lt;!-- add field :content --&amp;gt;
&amp;lt;div class="my-5"&amp;gt;
  &amp;lt;%= form.label :content %&amp;gt;
  &amp;lt;%= form.rich_text_area :content, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;!-- ... --&amp;gt;


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

&lt;/div&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/_post.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- add field :content --&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"my-5"&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="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;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;


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

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

&lt;span class="c"&gt;&amp;lt;!-- app/views/posts/show.html.erb --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- add field :content --&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"my-5 inline-block"&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="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;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Controller - Posts
```ruby
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  app/controllers/posts_controller.rb
&lt;/h1&gt;

&lt;p&gt;class PostsController &amp;lt; ApplicationController&lt;/p&gt;

&lt;h1&gt;
  
  
  ...
&lt;/h1&gt;

&lt;p&gt;private&lt;br&gt;
   def post_params&lt;br&gt;
     params.require(:post).permit(:title, :content) # add content&lt;br&gt;
   end&lt;br&gt;
end&lt;/p&gt;



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

### 3) Apply Turbo Frame to Posts pages
Clicking New Post will render the new post page into the index page
- View - Post index page
```erb


&amp;lt;!-- app/views/posts/index.html.erb --&amp;gt;
&amp;lt;div class="w-full"&amp;gt;
  &amp;lt;div class="flex justify-between items-center"&amp;gt;
    &amp;lt;h1 class="text-white text-lg font-bold text-4xl"&amp;gt;Posts&amp;lt;/h1&amp;gt;
    &amp;lt;%= link_to 'New Post', new_post_path,
      class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium",
      data: { 'turbo-frame': 'new_post' }
    %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;%= turbo_frame_tag :new_post %&amp;gt;

  &amp;lt;div class="min-w-full"&amp;gt;
    &amp;lt;%= turbo_frame_tag :posts do %&amp;gt;
      &amp;lt;%= render @posts %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;View - Post new page
```erb
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;lt;%= turbo_frame_tag :new_post do %&amp;gt;&lt;br&gt;
  &lt;/p&gt;
&lt;br&gt;
    &lt;h1&gt;New post&lt;/h1&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= render "form", post: @post %&amp;gt;

&amp;lt;%= link_to 'Back to posts', posts_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;br&gt;
&amp;lt;% end %&amp;gt;



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

### 4) Apply Turbo Stream on the view
- Add CRUD into Controller
```ruby


# app/controllers/posts_controller.rb
class PostsController &amp;lt; ApplicationController
  # ...
  def create
    @post = Post.new(post_params)

    respond_to do |format|
      if @post.save
        format.turbo_stream # add format turbo_stream
        format.html { redirect_to posts_path }
        format.json { render :show, status: :created, location: @post }
      else
        format.turbo_stream # add format turbo_stream
        format.html { render posts_path, status: :unprocessable_entity }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @post.update(post_params)
        format.turbo_stream # add format turbo_stream
        format.html { redirect_to posts_path, notice: "Post was successfully updated." }
        format.json { render :show, status: :ok, location: @post }
      else
        format.turbo_stream # add format turbo_stream
        format.html { render posts_path, status: :unprocessable_entity }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @post.destroy
    respond_to do |format|
      format.turbo_stream # add format turbo_stream
      format.html { redirect_to posts_url, notice: "Post was successfully destroyed." }
      format.json { head :no_content }
    end
  end
  # ...
end


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Create Turbo Streme template files

&lt;ul&gt;
&lt;li&gt;app/views/posts/create.turbo_stream.erb&lt;/li&gt;
&lt;li&gt;app/views/posts/update.turbo_stream.erb&lt;/li&gt;
&lt;li&gt;app/views/posts/destroy.turbo_stream.erb
```erb
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&amp;lt;% if &lt;a class="mentioned-user" href="https://dev.to/post"&gt;@post&lt;/a&gt;.errors.present? %&amp;gt;&lt;br&gt;
   &amp;lt;%= notice_stream(message: :error, status: 'red') %&amp;gt;&lt;br&gt;
   &amp;lt;%= form_post_stream(post: &lt;a class="mentioned-user" href="https://dev.to/post"&gt;@post&lt;/a&gt;) %&amp;gt;&lt;br&gt;
&amp;lt;% else %&amp;gt;&lt;br&gt;
   &amp;lt;%= notice_stream(message: :create, status: 'green') %&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;%= turbo_stream.replace :new_post do %&amp;gt;&lt;br&gt;
      &amp;lt;%= turbo_frame_tag :new_post %&amp;gt;&lt;br&gt;
   &amp;lt;% end %&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;%= turbo_stream.prepend 'posts', partial: 'post', locals: { post: &lt;a class="mentioned-user" href="https://dev.to/post"&gt;@post&lt;/a&gt; } %&amp;gt;&lt;br&gt;
&amp;lt;% end %&amp;gt;&lt;/p&gt;



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


&amp;lt;!-- app/views/posts/update.turbo_stream.erb --&amp;gt;
&amp;lt;% if @post.errors.present? %&amp;gt;
  &amp;lt;%= notice_stream(message: :error, status: 'red') %&amp;gt;

  &amp;lt;%= form_post_stream(post: @post) %&amp;gt;

&amp;lt;% else %&amp;gt;
  &amp;lt;%= notice_stream(message: :update, status: 'green') %&amp;gt;

  &amp;lt;%= turbo_stream.replace dom_id(@post), partial: 'post', locals: { post: @post } %&amp;gt;
&amp;lt;% end %&amp;gt;


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

&lt;/div&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/destroy.turbo_stream.erb --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;notice_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;message: :delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="s1"&gt;'green'&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="n"&gt;turbo_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt; &lt;span class="vi"&gt;@post&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;
  
  
  5) Implement Notification - Displaty notice
&lt;/h3&gt;

&lt;p&gt;Implement notice as a helper and allow routing then call controller to display in a view&lt;br&gt;
These steps use Stimulus to handle the Javascript&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create helper to be called from
```ruby
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  app/helpers/posts_helper.rb
&lt;/h1&gt;

&lt;p&gt;module PostsHelper&lt;br&gt;
  NOTICE = {&lt;br&gt;
    create: 'Post created successfully',&lt;br&gt;
    update: 'Post updated successfully',&lt;br&gt;
    delete: 'Post deleted successfully',&lt;br&gt;
    error: 'Something went wrong'&lt;br&gt;
  }.freeze&lt;/p&gt;

&lt;p&gt;def notice_stream(message:, status:)&lt;br&gt;
    turbo_stream.replace 'notice', partial: 'notice', locals: { notice: NOTICE[message], status: status }&lt;br&gt;
  end&lt;/p&gt;

&lt;p&gt;def form_post_stream(post:)&lt;br&gt;
    turbo_stream.replace 'form', partial: 'form', locals: { post: post }&lt;br&gt;
  end&lt;br&gt;
end&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Add Turbo Frame to main application file
```erb


&amp;lt;!-- app/views/layouts/application.html.erb --&amp;gt;
 &amp;lt;%= turbo_frame_tag :notice, class: 'w-full' do %&amp;gt;
 &amp;lt;% end %&amp;gt;


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Create Notice template in Post
```erb
&lt;/li&gt;
&lt;/ul&gt;

&lt;p id="notice"&gt;&amp;lt;%= notice %&amp;gt;&lt;/p&gt;



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

### 6) Implement Notification - Clear notice
- Create clear notification route
```ruby


&amp;lt;!-- app/views/posts/_form.html.erb ---&amp;gt;
# config/routes.rb
get '/notice', to: 'posts#clear_message'


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Add clear notification in Posts template
```erb
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;lt;%= turbo_frame_tag dom_id post do %&amp;gt;&lt;br&gt;
    &amp;lt;%= form_with(&lt;br&gt;
      model: post, &lt;br&gt;
      id: 'form',&lt;br&gt;
      class: "contents",&lt;br&gt;
      html: {&lt;br&gt;
        data: { controller: 'notice', action: 'submit-&amp;gt;notice#clear' }&lt;br&gt;
      }&lt;br&gt;
    ) do |form| %&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;!-- fields  ---&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;% end %&amp;gt;&lt;br&gt;
&amp;lt;% end %&amp;gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Trigger clear notification after config interval (5000 ms)
```ruby


# app/javascript/controllers/notice_controller.js
import { Controller } from "@hotwired/stimulus"
import { FetchRequest } from "@rails/request"

// Connects to data-controller="notice"
export default class extends Controller {
  clear(event) {
    event.preventDefault()

    setTimeout(async () =&amp;gt; {
      const request = new FetchRequest("get", '/notice', { responseKind: "turbo-stream" })
      await request.perform()
    }, 5000)

    event.target.requestSubmit()
  }
}


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Add Action to Post controller
```ruby
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  app/controllers/posts_controller.rb
&lt;/h1&gt;

&lt;p&gt;class PostsController &amp;lt; ApplicationController&lt;br&gt;
 # ... actions&lt;/p&gt;

&lt;p&gt;def clear_message&lt;br&gt;
  respond_to do |format|&lt;br&gt;
    format.turbo_stream&lt;br&gt;
  end&lt;br&gt;
 end&lt;br&gt;
end&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
### 7) Config landing page
- Redirect landing page to Posts index page
```ruby


# config/routes.rb
Rails.application.routes.draw do
  # Set Post index to landing page
  root 'posts#index'
end


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Start Rails server for verification
```ssh
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;rails s&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
![Rails 7 demo SPA screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1dn2im2e89qu4qym8rak.png)

- This app feature
- Display all Post on a single page
- Display Comment on each post when expanding
- CRUD Post
- CRUD Comment underneath Post
- Notification when create, update and delete when successful or failed

#### Resources
- Finished Codebase repo - [demo-blog-hotwire:initial_completed](https://github.com/aquadrehz/demo-blog-hotwire/tree/initial_completed)
- [Original workshop article by Alef Ojeda de Oliveira](https://dev.to/nemuba/blog-demo-using-rails-7-hotwire-rails-tailwindcss-stimulus-railsrequestjs-2c7a)

#### Read more
- [More Rails 7 Feature in detail](https://rubyonrails.org/2021/12/15/Rails-7-fulfilling-a-vision)
- [Rails, Hotwire, CableReady, and StimulusReflex are BFFs](https://dev.to/hopsoft/rails-hotwire-cableready-and-stimulusreflex-are-bffs-4a89)
- [Hotwire with previous Rails](https://blog.cloud66.com/taking-rails-to-the-next-level-with-hotwire/)
- [Rails 7 and Javascript](https://noelrappin.com/blog/2021/09/rails-7-and-javascript/)
- [Official Rails 7 release note](https://edgeguides.rubyonrails.org/7_0_release_notes.html)

#### Resource Attribute
[Blender](https://www.freepik.com/free-photo/man-adds-frozen-berriess-focused-blender-pot-with-before-making-make-tasty-smoothie-drink-refresh-summer-time-unfocused-glass-with-frozen-berries-front-near_11333837.htm#query=blender&amp;amp;position=2&amp;amp;from_view=search)
[Number art](https://www.freepik.com/free-vector/colorful-number-collection-with-flat-design_2303710.htm#query=7&amp;amp;position=16&amp;amp;from_view=search)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>rails</category>
      <category>javascript</category>
      <category>hotwire</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
