GitChat — le chat des développeurs sur GitHub

Un canal de discussion sur chaque dépôt, issue, organisation et équipe GitHub.

GitChat — le chat des développeurs sur GitHub
Rôle
Fondateur, développeur full stack
Stack
Laravel 12 · Extension MV3
Temps réel
Polling HTTP (3 s)
Statut
En ligne

Contexte

Sur GitHub, la discussion autour d’un dépôt se disperse entre les commentaires d’issues, un Slack ou un Discord à part, et des messages privés. Ces outils ne savent pas qui a accès à quel dépôt : on ouvre un salon, puis on gère les accès à la main, et ils dérivent.

Défi métier

Relier messagerie d'équipe et workflows GitHub pour la collaboration développeur.

Solution

GitChat ajoute un onglet de discussion directement sur les pages GitHub : un salon par dépôt, par issue ou pull request, par organisation ou par équipe, et des messages directs sur les profils. Un salon n’est ouvert qu’aux personnes qui ont déjà accès à la page sur GitHub, et ce droit est revérifié auprès de GitHub à chaque requête. Une application Laravel sert le web et l’API ; une extension Manifest V3 injecte l’onglet et affiche le chat dans le panneau latéral.

Résultat

En ligne, avec une extension pour Chrome et Firefox en trois langues, 19 types d’aperçus de liens, des notifications natives et un résumé quotidien par e-mail. L’exploitation est outillée : sonde de santé qui encode son verdict dans le code HTTP, deux battements de cœur, trois surveillants indépendants et un CHANGELOG généré depuis les tags.

Mon rôle

Fondateur et développeur full-stack

Architecture

Utilisateurs

  • Extension MV3 (onglet, panneau latéral, popup)
  • Service worker (seul détenteur du jeton)
  • Application web

Application

  • Laravel 12 · API Sanctum
  • Middlewares d’accès dépôt, organisation, équipe
  • File en base · worker systemd
  • Scheduler : 11 tâches
  • Sonde /health
  • MariaDB

Services externes

  • GitHub OAuth et API
  • Stripe · Lemon Squeezy
  • Resend
  • Sentry · PostHog
  • Discord · UptimeRobot (alertes)

Le parcours, étape par étape

  1. Connexion

    L’utilisateur se connecte avec GitHub OAuth sur l’application.

  2. Liaison de l’extension

    Depuis la popup, « Connecter » ouvre une page qui crée un jeton Sanctum et un ticket à usage unique valable deux minutes.

  3. Échange du ticket

    Un content script lit le ticket dans une balise meta ; le service worker l’échange contre le jeton. Le ticket ne transite jamais par une URL.

  4. Onglet GitChat

    Sur une page GitHub, l’extension déduit la portée — issue avant dépôt, équipe avant organisation — et ajoute l’onglet.

  5. Contrôle d’accès

    Le panneau latéral appelle l’API ; Laravel revérifie les droits auprès de GitHub. Un administrateur du dépôt crée le salon, les autres le rejoignent.

  6. Messages

    Le fil ouvert est interrogé toutes les trois secondes, l’extension toutes les minutes ; les salons dont le caractère public n’est pas établi sont caviardés.

Modèle de données

Les entités principales, leurs champs clés et leurs relations.

User

  • login · avatar_url
  • is_admin · is_banned
  • extension_connected_at
  • n—n Conversation
  • 1—n Message
  • 1—n Subscription

Conversation

  • type
  • max_members
  • requires_subscription
  • github_team_id
  • n—n User (membres)
  • 1—n Message

Message

  • content · type
  • reply_to
  • edited_at
  • 1—n Reaction
  • 1—n Mention
  • 1—n MessageAttachment

GithubRepoChat

  • owner · repo
  • is_private
  • visibility_checked_at
  • 1—1 Conversation
  • 1—n GithubIssueChat

GithubIssueChat

  • issue_number
  • kind (issue ou PR)
  • title · state
  • n—1 GithubRepoChat
  • 1—1 Conversation

GithubOrgChat · OrgTeamChat

  • org_login
  • équipe
  • 1—1 Conversation

Subscription

  • tier · billing_interval
  • status
  • price_per_user
  • 1—n Seat
  • 1—n Invoice
  • 1—n Conversation

Fiche technique complète

Langages
PHP 8.4, JavaScript, TypeScript (Playwright)
Framework
Laravel 12, Socialite, Sanctum
Front
Blade, Alpine.js, Tailwind 4, Vite 8, Chart.js, Prism
Extension
Manifest V3, esbuild ; permissions storage, activeTab, sidePanel, alarms ; notifications facultatives ; version Firefox
Base de données
MariaDB en production, MySQL 8 en développement, SQLite en CI
Files et planificateur
File en base de données, worker systemd sur les files default et mail, 11 tâches planifiées
Temps réel
Polling HTTP : 3 s pour le fil ouvert, 15 à 30 s pour les notifications web, 1 min pour l’extension
Authentification
GitHub OAuth ; jeton Sanctum à 7 capacités, valable 30 jours, remis par ticket unique ; anciens jetons révoqués
Paiement
Stripe ou Lemon Squeezy, au choix ; webhooks dédoublonnés
E-mail
Resend ; campagnes découpées en jobs à deux envois par seconde
Hébergement
Apache et PHP-FPM, déploiement scripté avec sauvegarde de la base avant chaque migration
CI/CD
3 workflows : tests sur runner auto-hébergé, reconstruction du zip de l’extension, sonde horaire externe
Tests
PHPUnit 11 (118 fichiers, environ 830 tests), Playwright (6 specs), node --test pour l’extension (68 tests)
Qualité
Pint, hook pre-push, Dependabot, versionnage automatique
Supervision
Sentry, PostHog, /health protégé (503 en cas d’échec), deux battements de cœur, chien de garde par cron, alertes Discord
Langues
Anglais, français, néerlandais (web et extension)
Sécurité
Récupération d’URL anti-SSRF (HTTPS, IP publiques, redirections contrôlées), CSP et HSTS, 8 limiteurs de débit

Fonctionnalités clés

  • Salons GitHub

    Par dépôt, issue ou PR, organisation et équipe, plus des messages directs.

  • Conversation

    Réactions, mentions, réponses, modification, pièces jointes et GIF.

  • Aperçus de liens

    19 types de cartes : dépôt, issue, gist, discussion, comparaison, YouTube…

  • Notifications

    Natives dans l’extension, et résumé quotidien des non-lus par e-mail.

  • Abonnements par siège

    Avec un fournisseur de paiement interchangeable.

  • RGPD en libre-service

    Export et suppression du compte.

Problèmes résolus

  1. Planificateur muet

    ProblèmeLe fichier de tâches renvoyait une closure que Laravel 11 n’appelait jamais : aucune tâche planifiée ne tournait, sans aucune erreur.

    SolutionTâches déclarées via la façade Schedule, et un test qui verrouille leur liste.

  2. Santé faussement verte

    ProblèmeLa route /up répond 200 même quand la base est tombée.

    SolutionUne route /health qui encode le verdict dans le code HTTP, et deux battements de cœur qui distinguent un worker inactif d’un worker mort.

  3. Faux succès nocturnes

    ProblèmeTrois jobs de synchronisation journalisaient « synced » sans rien faire, faute de jeton utilisateur côté planificateur.

    SolutionJobs supprimés au profit de lectures en direct avec le jeton de la personne connectée.

  4. Cadence irrégulière de GitHub Actions

    ProblèmeUne sonde planifiée toutes les heures n’a tourné que quatre fois en seize heures.

    SolutionUn chien de garde lancé par cron, hors de Laravel, qui n’alerte qu’aux changements d’état.

  5. Aperçus coupés au-delà de dix

    ProblèmeAvec une limite de 10 par minute, les cartes suivantes retombaient en simple lien.

    SolutionLimite portée à 60 par minute, les réponses étant déjà en cache.

Choix techniques

Choix Pourquoi
Polling plutôt que WebSockets Rien à exploiter en plus en production ; le fil est suspendu quand l’onglet est masqué.
Pas de permission « tabs » Elle afficherait l’avertissement « historique de navigation » et désactiverait l’extension chez les utilisateurs existants.
Un surveillant hors du serveur Une sonde qui tourne sur le serveur surveillé tombe avec lui.
Le jeton ne passe jamais par une URL Ticket unique dans une balise meta, CORS limité à l’identifiant fixe de l’extension.

Chronologie

  1. Décembre 2024 Premier commit
  2. Mai 2026 Pages publiques, i18n, palette de commandes
  3. Juin 2026 Durcissement SSRF, uploads et webhooks
  4. Août 2026 Extension Chrome et salons de dépôt
  5. Septembre 2026 Salons d’issue et de PR, supervision extérieure
  6. Octobre 2026 Version Firefox, notifications natives

En chiffres

550
commits, dont 520 de ma main
227
versions publiées
~900
tests (PHP et extension)
3
langues

Relevé dans le code source et l’historique Git du projet le 8 octobre 2026. Aucun chiffre d’usage ou de revenu n’est publié.

Projets similaires

SaaS
janv. 2022 — déc. 2022
MissionsCMS — projet Web App
Système de gestion de missions avec suivi et tableaux de bord.
Laravel, Livewire, Alpine.js, TailwindCSS
Voir le projet
SaaS
sept. 2025 — présent
Lodate — projet Web App
Système de gestion de rendez-vous avec rappels et interface épurée.
Laravel, Livewire, Alpine.js, TailwindCSS
Voir le projet
SaaS
janv. 2023 — présent
PanelRP — projet Laravel FiveM
Panel open source de contrôle serveur FiveM/QBCore avec outils admin.
Laravel, Livewire, Alpine.js, TailwindCSS
Voir le projet
SaaS
oct. 2024 — présent
Vetzy — projet Laravel SaaS
Plateforme SaaS vétérinaire de prise de rendez-vous pour cliniques et propriétaires d’animaux.
PHP, Laravel, Livewire, TailwindCSS, SaaS
Voir le projet

Disponible pour missions PHP / Laravel / WordPress / Silverstripe en Belgique et remote EU.