htmx-go-chat
htmx-go-chat copied to clipboard
Chat app written in Go with HTMX and SSE
HTMX Chat App - Go and SSE
A basic multi user chat web app built using Go, and using HTMX for all frontend and UI interactions. The chat system is based on Server Sent Events (SSE) rather than Websockets.
The app looks, feels and interacts like a SPA, without full page reloads, but has zero lines of JavaScript
Built using:
- Go
- Echo - Minimal web framework and router
- HTMX - High power tools for HTML
- Bulma - CSS framework
- Font Awesome - Icons
๐
โโโ app/ - Go source code for server and app
โโโ build/ - Docker and deployment scripts
โโโ templates/ - HTML templates & fragments used by the app
๐ Design Notes
The Go code resides in app/ directory and, comprises a single main package, breaking it up over multiple packages was deemed unnecessary.
server.goMain entry point and HTTP server, using Echo.routes.goAll HTTP routes and endpoints, most of the app logic is here, and mostly returns rendered HTML templates.renderer.goImplements a HTML template renderer using the html/template package, part of the Go standard library.database.goExtremely simple datastore to persist messages, uses SQLite and the modernc.org/sqlite driver to store messages.chat.goSee below.
All the HTML served by the app is held within the templates/ folder. This is a mixture of full pages like index.html and HTML fragments of various sizes used for different parts of the app, as well as any custom CSS.
The main views are the login template and the chat template which is only shown after users login. The term login is a misnomer here, all users have to do is enter their name to enter the chat, there is no formal login process or actual usernames & auth.
๐ญ Chat Broker
The chat broker is the core part of the app that handles multi-user interaction using Server Side Events (SSE).
The SSE implementation has been factored out into this repo benc-uk/go-rest-api. This generic broker provides the SSE stream handler, which holds open the HTTP connection and streams events as they arrive, plus a connection registry, which handles multiple client connections, using Go channels.
The broker uses generics and exposes callbacks/handlers for message formatting, and hooking into connection/disconnection events. As such, the code in chat.go uses these hooks as follows:
- Defines a
ChatMessagestruct type, used to send chat messages as SSE events. - An in-memory message store so we can send some previous history of messages when users connect.
- Message formatter, converting
ChatMessage's to HTML in a HTMX friendly way. - Handlers for connections/disconnections in order to notify other users.
One interesting thing about SSE is you can access the stream of events over a regular HTTP connection. So debugging and viewing the chat stream can be done by connecting to the /chat-stream URL directly in your browser.
๐งโ๐ป Developer Guide
Pre-reqs
- Go (v1.20+)
- A Linux compatible system with bash, make, curl etc
Makefile reference:
help ๐ฌ This help message :)
install-tools ๐ง Install dev tools into local project tools directory
watch ๐ฅ Run the server with reloading
run ๐ Run the server
run-container ๐ฆ Run from container
build ๐จ Build the server binary only
lint ๐ Lint & format check only, sets exit code on error for CI
lint-fix ๐ Lint & format, attempts to fix errors & modify code
image ๐ณ Build container image
push ๐ค Push container image to the image registry
deploy โ
Deploy to Azure
clean ๐งน Cleanup project
Running Locally
Quickly run the server
make run
Open http://localhost:8000 in a browser
To run with reloading/watching on code changes
make install-tools
make watch
๐ Building your own image
The makefile has two targets image and push which can be run to build and push an image. Set the variables IMAGE_NAME and VERSION to change the image name and tag. The image name should be fully qualified and include the registry if you are pushing it to one.
For example to build an image named bob/my-chatapp tagged with dev and pushed to the myreg.io registry, you would run:
make image push IMAGE_NAME=myreg.io/bob/my-chatapp VERSION=dev
You will need a container runtime and Docker compatible CLI installed.
โ Deploying to Azure
A script build/deploy.sh will deploy the app into Azure using Azure Container Apps. The script is fairly hardcoded and no effort has been made, to have this flexible & fully parameterized. The image will need to be pushed into a public & anonymous registry (e.g. GitHub Container Reg) for the script to work
I suggest looking at the deploy.sh script before running.
make deploy