MCPcopy Index your code
hub / github.com/centrifugal/grand-chat-tutorial

github.com/centrifugal/grand-chat-tutorial @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
128 symbols 352 edges 36 files 3 documented · 2%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

GrandChat — Django + React + Centrifugo messenger

This is the source code for the Centrifugo Chat / Messenger Tutorial.

GrandChat is a real-time WebSocket chat that goes beyond the usual basics — a simplified messenger (think Discord/Telegram/Slack) where a user can be a member of many rooms and receive updates from all of them on one screen, in real time.

Tech stack

  • Frontend: React + TypeScript (Vite), talking to the backend over a REST API and to Centrifugo over a WebSocket.
  • Backend: Django + Django REST Framework, with PostgreSQL as the source of truth.
  • Real-time: Centrifugo delivers events over WebSocket. The backend publishes events to Centrifugo over its HTTP API and/or via a transactional outbox / CDC (Debezium + Kafka).
  • Nginx serves frontend and backend from a single origin; JWT authenticates Centrifugo connections and authorizes channel subscriptions.

The whole stack runs with a single docker compose command.

Running locally

You need Docker with Docker Compose. From the repo root, build and start everything:

docker compose up --build

The first start takes a while (it also brings up Kafka, Debezium, Redis, Prometheus and Grafana). Wait until the logs settle.

Then seed a tiny demo dataset — two users you can log in as (alice and bob, both with password password) and a few rooms they both belong to:

docker compose exec backend python manage.py shell -c "from app.utils import setup_quickstart; setup_quickstart()"

Now open http://localhost:9000 and log in as alice. To see real-time in action, log in as bob in a second browser (or an incognito window, so you don't replace the alice session) and send messages between the two — they appear instantly, and room membership changes sync live too.

demo

Optional: an admin user

If you want the Django admin (to create rooms by hand, inspect data, etc.), create a superuser:

docker compose exec backend python manage.py createsuperuser

Then visit http://localhost:9000/admin.

Optional: large-scale dataset

To explore how the app scales (see the scaling chapter), you can generate a large dataset — 100k users and rooms with 100 / 1k / 10k / 100k members:

docker compose exec backend python manage.py shell -c "from app.utils import setup_dev; setup_dev()"

Note these users have random passwords (you won't log in as them) — they exist to make rooms large. Log in with your own superuser and use the Discover screen to join those rooms.

How broadcasting works

The backend can deliver real-time events to Centrifugo in several modes, selected by CENTRIFUGO_BROADCAST_MODE in backend/app/settings.py:

  • api — publish over the Centrifugo HTTP API (lowest latency, at-most-once).
  • outbox — transactional outbox table polled by Centrifugo (reliable).
  • cdc — Debezium reads the WAL and streams changes through Kafka to Centrifugo (reliable, minimal DB overhead).
  • api_cdc (default) — combine API (for latency) and CDC (for reliability); duplicates are dropped via idempotency keys.

Each mode relies on a matching Centrifugo consumer (api needs none, outbox needs the postgresql consumer, cdc/api_cdc need the kafka consumer). The shipped centrifugo/config.json already enables both consumers, so you can switch between modes by changing only this one setting. The option is documented in detail next to CENTRIFUGO_BROADCAST_MODE in backend/app/settings.py, and each mode is explained in the tutorial.

Useful endpoints

URL What
http://localhost:9000 The app
http://localhost:9000/admin Django admin
http://localhost:3000 Grafana (admin / admin)
http://localhost:9090 Prometheus

Push notifications

Web push notifications (an optional appendix) are disabled by default. Enabling them requires Centrifugo PRO and Firebase setup — follow the push notifications chapter and the comments next to PUSH_NOTIFICATIONS_ENABLED in backend/app/settings.py.

Extension points exported contracts — how you extend this code

ChatLayoutProps (Interface)
(no doc)
frontend/src/ChatLayout.tsx
ChatRoomDetailProps (Interface)
(no doc)
frontend/src/ChatRoomDetail.tsx
ChatLoginProps (Interface)
(no doc)
frontend/src/ChatLogin.tsx
ChatSearchProps (Interface)
(no doc)
frontend/src/ChatSearch.tsx
User (Interface)
(no doc)
frontend/src/types.ts

Core symbols most depended-on inside this repo

post
called by 8
backend/chat/views.py
create
called by 6
backend/chat/views.py
fetchRoom
called by 5
frontend/src/App.tsx
handleApiError
called by 4
frontend/src/App.tsx
setLoadingFlag
called by 4
frontend/src/ChatSearch.tsx
create_room
called by 4
backend/app/utils.py
fill_room
called by 4
backend/app/utils.py
getCSRFToken
called by 3
frontend/src/AppApi.tsx

Shape

Function 63
Class 32
Method 18
Interface 15

Languages

TypeScript51%
Python49%

Modules by API surface

frontend/src/App.tsx18 symbols
backend/chat/views.py18 symbols
backend/chat/serializers.py14 symbols
frontend/src/AppApi.tsx13 symbols
frontend/src/types.ts11 symbols
backend/chat/models.py10 symbols
frontend/src/ChatRoomDetail.tsx7 symbols
backend/app/views.py7 symbols
frontend/src/ChatSearch.tsx6 symbols
backend/chat/admin.py6 symbols
backend/app/utils.py5 symbols
frontend/src/PushNotification.tsx4 symbols

Datastores touched

grandchatDatabase · 1 repos

For agents

$ claude mcp add grand-chat-tutorial \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact