GitChat — Chat for GitHub developers

A chat channel on every GitHub repository, issue, organisation and team.

GitChat — Chat for GitHub developers
Role
Founder, full stack developer
Stack
Laravel 12 · MV3 extension
Real time
HTTP polling (3 s)
Status
Live

Context

On GitHub, discussion around a repository is scattered across issue comments, a separate Slack or Discord, and private messages. Those tools don’t know who can access which repository: you open a channel, then manage access by hand, and it drifts.

Business challenge

Bridge team chat and GitHub workflows for developer collaboration.

Solution

GitChat adds a chat tab right on GitHub pages: one channel per repository, issue or pull request, organisation or team, plus direct messages on profiles. A channel is only open to people who already have access to the page on GitHub, and that right is re-checked with GitHub on every request. A Laravel application serves the web app and the API; a Manifest V3 extension injects the tab and shows the chat in the side panel.

Outcome

Live, with an extension for Chrome and Firefox in three languages, 19 link-preview types, native notifications and a daily e-mail digest. Operations are tooled: a health probe that puts its verdict in the HTTP status, two heartbeats, three independent watchers and a CHANGELOG generated from tags.

My role

Founder & full-stack developer

Architecture

Users

  • MV3 extension (tab, side panel, popup)
  • Service worker (only token holder)
  • Web app

Application

  • Laravel 12 · Sanctum API
  • Repo, org and team access middleware
  • Database queue · systemd worker
  • Scheduler: 11 tasks
  • /health probe
  • MariaDB

External services

  • GitHub OAuth and API
  • Stripe · Lemon Squeezy
  • Resend
  • Sentry · PostHog
  • Discord · UptimeRobot (alerts)

The flow, step by step

  1. Sign-in

    The user signs in to the app with GitHub OAuth.

  2. Linking the extension

    From the popup, “Connect” opens a page that creates a Sanctum token and a single-use ticket valid for two minutes.

  3. Ticket exchange

    A content script reads the ticket from a meta tag; the service worker exchanges it for the token. The ticket never travels in a URL.

  4. GitChat tab

    On a GitHub page, the extension works out the scope — issue before repository, team before organisation — and adds the tab.

  5. Access check

    The side panel calls the API; Laravel re-checks permissions with GitHub. A repository admin creates the channel, others join it.

  6. Messages

    The open thread is polled every three seconds, the extension every minute; channels whose public status isn’t established are redacted.

Data model

The main entities, their key fields and their 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 (members)
  • 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 or PR)
  • title · state
  • n—1 GithubRepoChat
  • 1—1 Conversation

GithubOrgChat · OrgTeamChat

  • org_login
  • team
  • 1—1 Conversation

Subscription

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

Full technical sheet

Languages
PHP 8.4, JavaScript, TypeScript (Playwright)
Framework
Laravel 12, Socialite, Sanctum
Front end
Blade, Alpine.js, Tailwind 4, Vite 8, Chart.js, Prism
Extension
Manifest V3, esbuild; storage, activeTab, sidePanel and alarms permissions; optional notifications; Firefox build
Database
MariaDB in production, MySQL 8 in development, SQLite in CI
Queues and scheduler
Database queue, systemd worker on the default and mail queues, 11 scheduled tasks
Real time
HTTP polling: 3 s for the open thread, 15–30 s for web notifications, 1 min for the extension
Authentication
GitHub OAuth; Sanctum token with 7 abilities, valid 30 days, handed over by a single-use ticket; old tokens revoked
Payments
Stripe or Lemon Squeezy, swappable; deduplicated webhooks
E-mail
Resend; campaigns split into jobs at two sends per second
Hosting
Apache and PHP-FPM, scripted deployment with a database backup before every migration
CI/CD
3 workflows: tests on a self-hosted runner, extension zip rebuild, hourly external probe
Tests
PHPUnit 11 (118 files, about 830 tests), Playwright (6 specs), node --test for the extension (68 tests)
Quality
Pint, pre-push hook, Dependabot, automatic versioning
Monitoring
Sentry, PostHog, protected /health (503 on failure), two heartbeats, cron watchdog, Discord alerts
Languages (UI)
English, French, Dutch (web and extension)
Security
SSRF-safe URL fetching (HTTPS, public IPs, checked redirects), CSP and HSTS, 8 rate limiters

Key features

  • GitHub channels

    Per repository, issue or PR, organisation and team, plus direct messages.

  • Conversation

    Reactions, mentions, replies, editing, attachments and GIFs.

  • Link previews

    19 card types: repository, issue, gist, discussion, compare, YouTube…

  • Notifications

    Native in the extension, plus a daily e-mail digest of unread messages.

  • Per-seat subscriptions

    With a swappable payment provider.

  • Self-service GDPR

    Account export and deletion.

Problems solved

  1. Silent scheduler

    ProblemThe schedule file returned a closure Laravel 11 never called: no scheduled task ran, and nothing reported it.

    FixTasks declared through the Schedule facade, and a test that locks their list.

  2. False green health

    ProblemThe /up route answers 200 even when the database is down.

    FixA /health route that puts the verdict in the HTTP status, and two heartbeats that tell an idle worker from a dead one.

  3. Fake nightly successes

    ProblemThree sync jobs logged “synced” while doing nothing, as the scheduler had no user token.

    FixJobs removed in favour of live reads with the signed-in user’s token.

  4. Irregular GitHub Actions cadence

    ProblemAn hourly scheduled probe ran only four times in sixteen hours.

    FixA cron watchdog, outside Laravel, that only alerts on state changes.

  5. Previews cut off after ten

    ProblemWith a limit of 10 per minute, later cards fell back to plain links.

    FixLimit raised to 60 per minute, as responses were already cached.

Technical choices

Choice Why
Polling rather than WebSockets Nothing extra to run in production; the thread pauses when the tab is hidden.
No “tabs” permission It would show a “browsing history” warning and disable the extension for existing users.
A watcher off the server A probe running on the monitored server goes down with it.
The token never travels in a URL Single-use ticket in a meta tag, CORS restricted to the extension’s fixed ID.

Timeline

  1. December 2024 First commit
  2. May 2026 Public pages, i18n, command palette
  3. June 2026 SSRF, upload and webhook hardening
  4. August 2026 Chrome extension and repository channels
  5. September 2026 Issue and PR channels, external monitoring
  6. October 2026 Firefox build, native notifications

In numbers

550
commits, 520 of them mine
227
released versions
~900
tests (PHP and extension)
3
languages

Taken from the project’s source code and Git history on 8 October 2026. No usage or revenue figures are published.

Related projects

SaaS
Jan 2022 — Dec 2022
MissionsCMS — Web App project
Mission management system with tracking dashboards and workflow tools.
Laravel, Livewire, Alpine.js, TailwindCSS
View project
SaaS
Sep 2025 — present
Lodate — Web App project
Appointment scheduling system with reminders and clean interface navigation.
Laravel, Livewire, Alpine.js, TailwindCSS
View project
SaaS
Jan 2023 — present
PanelRP — Laravel FiveM project
Open-source FiveM/QBCore server admin panel with roleplay tooling.
Laravel, Livewire, Alpine.js, TailwindCSS
View project
SaaS
Oct 2024 — present
Vetzy — Laravel SaaS project
SaaS veterinary booking platform for clinics and pet owners with scheduling, notifications and client portal.
PHP, Laravel, Livewire, TailwindCSS, SaaS
View project

Available for PHP / Laravel / WordPress / Silverstripe missions in Belgium and remote EU.