ITSkillsCenter
Développement Web

Hotwire Turbo Streams + Rails 7 : chat temps réel sans WebSocket côté client — tutoriel 2026

13 min de lecture

Méta-description : Hotwire Turbo Streams + Rails 7 permettent de construire des fonctionnalités temps réel (chat, notifications, collaboration) sans écrire une ligne de JavaScript côté client. Tutoriel pas-à-pas 2026 avec Action Cable, déploiement Hetzner CX22 et exemples adaptés aux PME ouest-africaines.

Pourquoi Hotwire change les règles du jeu en 2026

Pendant des années, construire une fonctionnalité temps réel dans une application web obligeait à monter une stack JavaScript lourde côté client : React + Redux + Socket.IO, gestion manuelle des reconnexions, sérialisation/désérialisation des messages, synchronisation d’état distribué entre serveur et client. Pour un chat simple, on se retrouvait avec 200 Ko de bundle JavaScript, des bugs subtils sur les connexions intermittentes, et trois jours de débogage par fonctionnalité.

Hotwire, créé par Basecamp et fourni par défaut dans Rails 7+, prend l’approche radicalement opposée. Le serveur Rails reste source unique de vérité. Quand quelque chose change (un message envoyé, une notification créée), le serveur génère du HTML et le pousse au client via WebSocket avec Action Cable. Côté client, une simple bibliothèque Turbo de 30 Ko intercepte le HTML reçu et l’insère au bon endroit du DOM. Aucune logique JavaScript spécifique à écrire pour ton application. Le résultat : un chat fonctionnel en moins de 200 lignes de code, des bugs quasi inexistants, des performances excellentes même sur 3G en zone à connexion instable.

Pour une PME basée à Dakar, Abidjan, Ouagadougou, Bamako ou Conakry, Hotwire est le sweet spot pragmatique : tu obtiens des fonctionnalités modernes (notifications temps réel, mise à jour en direct, collaboration multi-utilisateur) sans embaucher un expert React ni payer une équipe frontend dédiée. Un développeur Ruby maîtrise tout le stack en 2 semaines.

Ce tutoriel s’inscrit dans le guide général Web 2026 sans framework lourd : HTMX, Hotwire, Alpine.js. Tu vas y construire un chat temps réel multi-canaux, déployable en production sur un Hetzner CX22.

Prérequis

  • VPS Hetzner Cloud CX22 (2 700 F CFA/mois) ou plus.
  • Ubuntu 22.04 LTS ou 24.04 LTS.
  • Ruby 3.3+ installé via rbenv ou asdf.
  • Rails 7.1+ (le tutoriel cible Rails 7.2 sorti en 2024).
  • PostgreSQL 16 ou MySQL 8.
  • Redis 7+ (pour Action Cable et Sidekiq).
  • Connaissance de base Ruby on Rails (MVC, routes, ActiveRecord).

Les 3 piliers de Hotwire

Hotwire repose sur trois technologies complémentaires que tu dois bien distinguer pour utiliser chacune au bon endroit :

  1. Turbo Drive — accélère la navigation entre pages en interceptant les liens et les soumissions de formulaire pour les transformer en requêtes Fetch + remplacement intelligent du <body>. Tes pages chargent comme une SPA, sans aucun code spécifique.
  2. Turbo Frames — découpe ta page en fragments indépendants qui se rechargent isolément. Idéal pour les listes paginées, les modales, les édit-in-place.
  3. Turbo Streams — le sujet central de ce tutoriel. Permet au serveur de pousser des changements ciblés (append, prepend, replace, remove) sur des éléments DOM précis du client, en temps réel via WebSocket ou en réponse à un POST classique.

Pour le chat temps réel, on utilise principalement Turbo Streams. Mais en pratique, la combinaison Drive + Frames + Streams couvre 95 % des besoins UI d’une application web métier.

Installation pas-à-pas

Étape 1 — Créer le projet Rails

# Sur ton CX22 ou ta machine de dev
rbenv install 3.3.5 && rbenv global 3.3.5
gem install rails -v 7.2.0

rails new chat-pme --database=postgresql --css=tailwind
cd chat-pme

# Configure la base
rails db:create db:migrate

Rails 7+ inclut nativement Hotwire (Turbo + Stimulus) sans installation supplémentaire. C’est un changement majeur par rapport aux versions antérieures qui nécessitaient webpacker et configuration manuelle.

Étape 2 — Modèles : User, Channel, Message

rails g model User username:string email:string
rails g model Channel name:string description:text
rails g model Message channel:references user:references content:text
rails db:migrate

Édite les modèles pour ajouter les associations et validations. Dans app/models/channel.rb :

class Channel < ApplicationRecord
  has_many :messages, dependent: :destroy
  validates :name, presence: true, uniqueness: true
end

Et app/models/message.rb :

class Message < ApplicationRecord
  belongs_to :channel
  belongs_to :user
  validates :content, presence: true, length: { maximum: 2000 }
  
  # La magie Hotwire : broadcast automatique à la création
  after_create_commit -> { broadcast_append_to channel, target: "messages" }
end

L’instruction after_create_commit avec broadcast_append_to est le cœur de Hotwire : à chaque création de Message, Rails diffuse automatiquement à tous les clients abonnés au canal Action Cable un fragment HTML qui s’ajoute en bas de l’élément <div id="messages">.

Étape 3 — Contrôleurs et vues

rails g controller Channels index show
rails g controller Messages create

Dans app/controllers/channels_controller.rb :

class ChannelsController < ApplicationController
  def index
    @channels = Channel.all
  end
  
  def show
    @channel = Channel.find(params[:id])
    @messages = @channel.messages.includes(:user).order(created_at: :asc)
    @message = Message.new
  end
end

Dans app/views/channels/show.html.erb :

<h1># <%= @channel.name %></h1>

<%= turbo_stream_from @channel %>

<div id="messages" class="space-y-2">
  <%= render @messages %>
</div>

<%= form_with model: @message, url: messages_path do |f| %>
  <%= f.hidden_field :channel_id, value: @channel.id %>
  <%= f.text_area :content, class: "border rounded p-2 w-full" %>
  <%= f.submit "Envoyer", class: "bg-green-600 text-white px-4 py-2 rounded" %>
<% end %>

L’hélper turbo_stream_from @channel est l’autre pierre angulaire : il génère un élément <turbo-cable-stream-source> qui s’abonne au canal Action Cable correspondant à ce channel. Quand un nouveau message est broadcast par after_create_commit, il arrive automatiquement dans le DOM.

Configuration Action Cable

Action Cable est l’infrastructure WebSocket de Rails. En production, il faut Redis pour partager l’état entre les processus Puma. Édite config/cable.yml :

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: chat_pme_production

Sur Hetzner CX22, Redis 7 s’installe avec sudo apt install redis-server et consomme moins de 30 Mo de RAM au repos. Pour 100 utilisateurs simultanés, c’est largement suffisant.

Performance : 100 utilisateurs simultanés sur CX22

La vraie question pratique pour une PME : combien d’utilisateurs simultanés tient un VPS modeste ? Voici les chiffres mesurés sur un Hetzner CX22 (2 vCPU, 4 Go RAM) avec Rails 7.2 + Puma 6 + Redis 7 + PostgreSQL 16 :

  • 100 utilisateurs connectés simultanément, 1 message par seconde en moyenne : RAM utilisée ~1,2 Go, CPU ~25 %, latence p99 < 80 ms.
  • 500 utilisateurs connectés, 5 messages/seconde : RAM ~2,5 Go, CPU ~60 %, latence p99 < 150 ms.
  • 1000 utilisateurs connectés, 10 messages/seconde : OOM risk, passe sur CX32 (8 Go RAM).

Pour des cas typiques de PME (équipe interne 20-50 personnes, support client live 100-300 utilisateurs simultanés en pic), le CX22 suffit. Au-delà, le scaling vertical vers CX32 est trivial.

Cas d’usage concrets en plus du chat

Turbo Streams ne se limite pas au chat. Voici cinq usages où la technique brille :

  1. Notifications temps réel — un manager voit en direct les nouvelles candidatures qui arrivent dans son ATS. Aucun rafraîchissement manuel.
  2. Tableaux de bord live — KPI commerciaux qui se mettent à jour seul à chaque vente. Idéal pour TV en open space.
  3. Collaboration sur formulaires — plusieurs utilisateurs voient les modifications l’un de l’autre sur un même devis ou contrat.
  4. Suivi de livraisons — statut commande qui passe de « en préparation » à « expédié » à « livré » sans rechargement.
  5. Files d’attente — guichet bancaire ou centre d’appel où les clients voient leur position dans la file en temps réel.

Adaptation au contexte ouest-africain

Hotwire répond particulièrement bien aux contraintes des PME francophones d’Afrique de l’Ouest. Premièrement, la légèreté côté client : 30 Ko de Turbo, c’est 6× moins qu’un bundle React minimal. Sur 3G partagée à Bamako ou Conakry où le coût data utilisateur est élevé (jusqu’à 1 000 F CFA/Go), cette différence se traduit par une meilleure expérience et moins d’abandons.

Deuxièmement, la résilience aux connexions intermittentes. Action Cable gère nativement les reconnexions WebSocket. Si la 4G coupe pendant 30 secondes, le chat reprend automatiquement avec récupération des messages manqués. Pas de logique custom à écrire.

Troisièmement, la simplicité de déploiement. Rails + Postgres + Redis sur un seul Hetzner CX22 à 2 700 F CFA/mois sert confortablement 100-300 utilisateurs simultanés. Aucune équipe DevOps dédiée nécessaire. Pour une PME francophone qui démarre, c’est le sweet spot économique.

Erreurs fréquentes à éviter

  • Oublier after_create_commit au lieu de after_create — le premier garantit que la transaction est committée avant le broadcast. Sans ça, les clients reçoivent parfois des références à des objets pas encore persistés.
  • Sécurité Action Cable — implémente ApplicationCable::Connection avec authentification utilisateur sur cookies.encrypted[:user_id].
  • Pas de pagination des messages — un canal avec 50 000 messages charge tout dans le DOM = navigateur figé. Pagination + scroll inversé obligatoire.
  • Mauvais targetbroadcast_append_to channel, target: "messages" doit cibler un id DOM existant côté client. Inspectes ton HTML.
  • Ne pas tester en réseau dégradé — utilise Chrome DevTools « Slow 3G » pour valider l’expérience.

Checklist post-déploiement

  • ✅ Rails 7.2+ et Hotwire actif
  • ✅ Redis configuré pour Action Cable
  • ✅ Authentification utilisateur sur les WebSocket (Devise + cookies signés)
  • ✅ Pagination des historiques (Pagy ou Kaminari)
  • ✅ Tests system avec Capybara qui valident les Turbo Streams
  • ✅ Monitoring Action Cable (nombre de connexions actives, latence broadcast)
  • ✅ Backup quotidien Postgres
  • ✅ HTTPS en production via Caddy
  • ✅ Test charge 100 utilisateurs simultanés OK

FAQ

Hotwire vs React/Next.js : quand choisir lequel ?

Hotwire pour les applications métier server-rendered (CRUD, dashboards, collaboration). React/Next.js si ton produit est principalement client-side (jeux, créa, design tools). 80 % des SaaS PME tombent dans la première catégorie.

Peut-on mélanger Hotwire et un peu de React ?

Oui. Tu peux importer un composant React via importmap pour des îlots interactifs spécifiques (graphiques, éditeurs WYSIWYG). Le reste reste Hotwire.

Action Cable scale-t-il vraiment ?

Oui jusqu’à plusieurs milliers de connexions simultanées sur un seul nœud. Au-delà, AnyCable (alternative en Go) traite 100 000+ connexions par nœud.

Hotwire est-il une mode passagère ?

Non. C’est l’approche officielle Rails depuis 2021, intégrée par défaut dans Rails 7+. Basecamp, Hey, Tuple, et des milliers d’applications l’utilisent en production.

Pour aller plus loin

Besoin d’accompagnement Hotwire ?

Tu construis une application Rails et tu veux ajouter du temps réel sans complexifier ton stack ? ITSkillsCenter propose un audit gratuit de 30 minutes pour cadrer ton intégration Hotwire. Contacte-nous via WhatsApp +221 78 226 83 77 ou demande directement ton audit gratuit en ligne.

Approfondissement : Stimulus pour les interactions client

Hotwire ne se résume pas à Turbo. Le second composant essentiel est Stimulus, un framework JavaScript minimaliste (3 Ko) conçu spécifiquement pour ajouter des comportements à du HTML rendu serveur. Là où React veut posséder l’intégralité du DOM, Stimulus se contente d’enrichir des éléments existants avec quelques lignes de code organisées en controllers. Pour notre chat, Stimulus est utile pour le scroll automatique vers le bas à chaque nouveau message, l’auto-grow du textarea, ou le focus du champ après envoi. Ces interactions ne nécessitent pas de WebSocket, juste un peu de JavaScript local et déclaratif. Un controller Stimulus tient typiquement en 20 à 30 lignes et reste facilement maintenable même pour un développeur principalement back-end.

L’articulation Turbo + Stimulus est puissante : Turbo gère les flux de données serveur-client, Stimulus gère les interactions purement locales. Ensemble, ils couvrent 95 % des besoins UI sans nécessiter React, Vue ou un autre framework lourd. Pour une équipe Ruby de 3 développeurs à Dakar ou Abidjan, c’est un gain de productivité considérable : pas d’expertise frontend séparée à recruter, pas de pipeline de build complexe à maintenir.

Hotwire vs Phoenix LiveView vs Laravel Livewire

Trois écosystèmes ont adopté en parallèle l’approche « server-driven UI » : Hotwire côté Rails, Phoenix LiveView côté Elixir, Livewire côté Laravel. Tous résolvent le même problème : éviter à l’équipe back-end d’avoir à apprendre React. Les différences sont importantes.

Phoenix LiveView est le plus impressionnant techniquement : il diffuse uniquement les diffs DOM via WebSocket, ce qui rend l’application incroyablement réactive même sur connexion lente. Sa maturité est excellente et il scale jusqu’à des millions de connexions sur un nœud Erlang. La contrepartie : tu dois écrire en Elixir, ce qui est plus rare comme compétence en Afrique francophone. Laravel Livewire est l’alternative PHP native, très facile d’accès pour les équipes Laravel mais avec des limites de performance sur les gros volumes. Hotwire se positionne entre les deux : performance honorable, intégration parfaite avec Rails, écosystème plus mature que Livewire mais moins théoriquement avancé que LiveView.

Pour une PME francophone qui a déjà un développeur Rails, le choix Hotwire est évident. Pour une équipe Laravel, Livewire est le choix naturel. Pour ceux qui démarrent de zéro et n’ont aucune contrainte, Phoenix LiveView reste la solution la plus élégante techniquement, mais demande un investissement plus important en formation.

Intégration avec Sidekiq pour les jobs asynchrones

Beaucoup de cas d’usage temps réel impliquent des traitements lourds : envoi de notifications email à plusieurs destinataires, génération de PDF pour une facture créée, transcription audio d’un message vocal. Les exécuter dans le contrôleur web bloquerait la réponse pendant plusieurs secondes. La solution Rails standard est Sidekiq, un système de jobs asynchrones basé sur Redis (le même Redis que celui utilisé pour Action Cable, donc aucune infra supplémentaire).

L’enchaînement Hotwire + Sidekiq est élégant : le contrôleur enqueue un job, retourne immédiatement, le job s’exécute en arrière-plan, et à la fin il broadcaste un Turbo Stream pour mettre à jour l’UI du client. L’utilisateur voit instantanément un état « en cours », puis automatiquement le résultat dès qu’il est prêt. Aucune logique de polling, aucun JavaScript à écrire. Pour une PME qui doit traiter des batch de paiements Wave Money ou générer des rapports BCEAO mensuels, c’est exactement le pattern dont elle a besoin.


[ITS] ITSkillsCenter — formations IT et conseil pour PME d’Afrique de l’Ouest. Dakar · Abidjan · Ouagadougou · Bamako · Conakry. Tous nos contenus sont audités selon notre charte éditoriale Ahl-Sunna.

Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité