Skip to content

Instantly share code, notes, and snippets.

@Blacksmoke16
Last active November 29, 2025 04:15
Show Gist options
  • Select an option

  • Save Blacksmoke16/7411a47516be94a9080ffab95af0b8aa to your computer and use it in GitHub Desktop.

Select an option

Save Blacksmoke16/7411a47516be94a9080ffab95af0b8aa to your computer and use it in GitHub Desktop.
Crystal Client code for publishing to a Mercure Hub
MERCURE_URL=http://localhost:8000/.well-known/mercure
MERCURE_JWT_SECRET=eyJhbGciOiJIUzI1NiJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdLCJzdWJzY3JpYmUiOlsiaHR0cHM6Ly9leGFtcGxlLmNvbS9teS1wcml2YXRlLXRvcGljIiwie3NjaGVtZX06Ly97K2hvc3R9L2RlbW8vYm9va3Mve2lkfS5qc29ubGQiLCIvLndlbGwta25vd24vbWVyY3VyZS9zdWJzY3JpcHRpb25zey90b3BpY317L3N1YnNjcmliZXJ9Il0sInBheWxvYWQiOnsidXNlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vdXNlcnMvZHVuZ2xhcyIsInJlbW90ZUFkZHIiOiIxMjcuMC4wLjEifX19.KKPIikwUzRuB3DTpVw6ajzwSChwFw5omBMmMcWKiDcM

Athena + Mercure

  1. docker compose up
  2. shards run server
  3. Open http://localhost:8000/.well-known/mercure/ui/ and http://localhost:8080/ in separate tabs
    1. Open console on the :8080 tab
    2. Paste in https://example.com/my-topic as the topic to get updates for and hit Subscribe
  4. curl http://localhost:3000/book/123
  5. Should see the update data in both the Mercure UI and console of the :8080 tab
services:
nginx:
image: nginx
volumes:
- ./index.html:/usr/share/nginx/html/index.html:ro
ports:
- '8080:80'
mercure:
image: dunglas/mercure
restart: unless-stopped
environment:
SERVER_NAME: ':80' # Disable HTTPS for local dev
MERCURE_PUBLISHER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
MERCURE_EXTRA_DIRECTIVES: |
cors_origins http://localhost:8080
anonymous
MERCURE_CORS_ALLOWED_ORIGINS: '*'
command: /usr/bin/caddy run --config /etc/caddy/dev.Caddyfile # Enable dev mode
ports:
- '8000:80'
volumes:
- mercure_data:/data
- mercure_config:/config
volumes:
mercure_data:
mercure_config:
<!doctype html>
<html>
<body>
<script type="application/javascript">
const url = new URL("http://localhost:8000/.well-known/mercure");
url.searchParams.append("topic", "https://example.com/my-topic");
const eventSource = new EventSource(url, { withCredentials: true });
console.log("listening...");
eventSource.onmessage = (e) => console.log(e);
</script>
<h2>Mercure Testing</h2>
</body>
</html>
require "athena"
require "athena-mercure"
require "athena-dotenv"
Athena::Dotenv.load
@[ADI::Register(_token: ENV["MERCURE_JWT_SECRET"])]
@[ADI::AsAlias(AMC::TokenProvider::Interface)]
struct AMC::TokenProvider::Static; end
@[ADI::Register(_url: ENV["MERCURE_URL"])]
@[ADI::AsAlias(AMC::Hub::Interface)]
class AMC::Hub; end
@[ADI::Register]
class BookController < ATH::Controller
def initialize(@hub : AMC::Hub::Interface); end
@[ARTA::Get("/book/{id}")]
def book(id : Int32) : String
# pp @hub
update = AMC::Update.new(
"https://example.com/my-topic",
{status: "Secretly checked out #{id}"}.to_json,
)
@hub.publish update
end
end
ATH.run
version: 2.0
shards:
athena:
git: https://github.com/athena-framework/framework.git
version: 0.21.1
athena-clock:
git: https://github.com/athena-framework/clock.git
version: 0.2.0
athena-console:
git: https://github.com/athena-framework/console.git
version: 0.4.2
athena-contracts:
git: https://github.com/athena-framework/contracts.git
version: 0.1.0
athena-dependency_injection:
git: https://github.com/athena-framework/dependency-injection.git
version: 0.4.4
athena-dotenv:
git: https://github.com/athena-framework/dotenv.git
version: 0.1.3
athena-event_dispatcher:
git: https://github.com/athena-framework/event-dispatcher.git
version: 0.4.0
athena-image_size:
git: https://github.com/athena-framework/image-size.git
version: 0.1.4
athena-mercure:
git: https://github.com/athena-framework/mercure.git
version: 0.1.0+git.commit.0edd85b94ba285cbf5ddadf4273389e5f45a6513
athena-mime:
git: https://github.com/athena-framework/mime.git
version: 0.2.1
athena-negotiation:
git: https://github.com/athena-framework/negotiation.git
version: 0.2.0
athena-routing:
git: https://github.com/athena-framework/routing.git
version: 0.1.12
athena-serializer:
git: https://github.com/athena-framework/serializer.git
version: 0.4.2
athena-validator:
git: https://github.com/athena-framework/validator.git
version: 0.4.1
bindata:
git: https://github.com/spider-gazelle/bindata.git
version: 2.1.1
ed25519:
git: https://github.com/spider-gazelle/ed25519.git
version: 1.1.0
jwt:
git: https://github.com/crystal-community/jwt.git
version: 1.7.1
openssl_ext:
git: https://github.com/spider-gazelle/openssl_ext.git
version: 2.8.2
name: athena-mercure
version: 0.1.0
description: |
Proof of concept Athena Mercure integration
targets:
server:
main: ./server.cr
dependencies:
athena:
github: athena-framework/framework
version: ~> 0.21
athena-dotenv:
github: athena-framework/dotenv
version: ~> 0.1.0
athena-mercure:
github: athena-framework/mercure
branch: master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment