-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 864e61f
Showing
162 changed files
with
27,339 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "Docusaurus Development Environment", | ||
"image": "mcr.microsoft.com/devcontainers/javascript-node:22", | ||
"postCreateCommand": "npm install", | ||
"customizations": { | ||
"vscode": { | ||
"extensions": [ | ||
"dbaeumer.vscode-eslint", | ||
"esbenp.prettier-vscode", | ||
"unifiedjs.vscode-mdx" | ||
], | ||
"settings": { | ||
"editor.formatOnSave": true, | ||
"editor.defaultFormatter": "esbenp.prettier-vscode" | ||
} | ||
} | ||
}, | ||
"forwardPorts": [3000], | ||
"portsAttributes": { | ||
"3000": { | ||
"label": "Docusaurus", | ||
"onAutoForward": "openBrowser" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: Build and publish static site | ||
on: | ||
push: {} | ||
pull_request: | ||
branches: [main] | ||
jobs: | ||
publish: | ||
name: Build and publish | ||
runs-on: ubuntu-latest | ||
|
||
# Permissions are needed for GitHub's OIDC Token endpoint. | ||
permissions: | ||
id-token: write | ||
contents: read | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: "22.x" | ||
cache: npm | ||
- run: npm ci | ||
- run: npm run build | ||
|
||
- name: Assume AWS Role | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
if: github.ref == 'refs/heads/main' | ||
with: | ||
role-to-assume: arn:aws:iam::080825576347:role/GitHubActionsHotsockWebsiteDeployRole | ||
aws-region: us-west-2 | ||
- name: Publish site to S3 | ||
if: github.ref == 'refs/heads/main' | ||
run: | | ||
aws s3 sync \ | ||
build/ \ | ||
s3://hotsockwebsite-bucket-1b98507gb6g3t \ | ||
--delete |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Dependencies | ||
/node_modules | ||
|
||
# Production | ||
/build | ||
|
||
# Generated files | ||
.docusaurus | ||
.cache-loader | ||
|
||
# Misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Hotsock Website | ||
|
||
This is the source code for the [Hotsock website, docs, and examples](https://www.hotsock.io). | ||
|
||
## Develop locally | ||
|
||
``` | ||
npm install | ||
npm run start | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
--- | ||
slug: hotsock-v1.0 | ||
title: Hotsock v1.0 Released! | ||
authors: [james] | ||
tags: [] | ||
--- | ||
|
||
Real-time functionality is a core expectation in modern applications. Whether you're building complex user interfaces, showing messages and typing indicators for a chat product, keeping player moves up-to-date in a collaborative game, or one of endless other multi-player use cases, **instant feedback is crucial for a great user experience**. | ||
|
||
Implementing real-time features often requires integrating with a third-party service and dealing with fixed limits, difficult sales processes, and questionable or unstable SDKs. Plus, you're sending private data out of your systems to external providers that are potentially thousands of miles from you and your customers' geographic locations. And who knows, they might also be using your data to train their latest AI model. 🙄 | ||
|
||
Starting today, you can install a full-featured, real-time WebSockets service **securely and privately in your own AWS account** in any of the [22 supported commercial AWS regions](/docs/installation/region-support) around the world, with [more regions to come](/docs/installation/region-support/#unsupported-regions) in the future. | ||
|
||
{/* truncate */} | ||
|
||
### What's in the box | ||
|
||
It includes these features and so much more — | ||
|
||
- [Fine-grained permissions](/docs/connections/claims) for authorizing private channel access using JSON Web Tokens (JWTs). | ||
- Both [server-initiated](/docs/server-api/publish-messages/) and [client-initiated](/docs/channels/client-messages/) messages are supported for publishing. | ||
- [Standard channels](/docs/channels/standard) for updating any number of connected clients with real-time data from your application backend. | ||
- [Presence channels](/docs/channels/presence) for tracking who's online or what client devices are connected. | ||
- [Pub/sub events with EventBridge or SNS](/docs/server-api/events) for webhook behavior to notify your application about things happening inside your Hotsock installation. | ||
- [Custom domains](/docs/installation/custom-domains) for your WebSockets endpoint so you can maintain consistent branding and customer trust. | ||
- A [web console](/docs/server-api/web-console) for debugging channel subscriptions, messages, and authorization. | ||
|
||
With support for regions across the globe, your customers can connect with the low latency they're accustomed to and your business can meet any data residency and compliance requirements. | ||
|
||
Hotsock provides powerful, intuitive, and [stable](/docs/installation/versioning/) APIs for building real-time applications while standing on the shoulders of a giant — AWS. | ||
|
||
### Publish real-time messages | ||
|
||
Use the AWS SDK you're already familiar with to [publish messages via AWS Lambda](/docs/server-api/publish-messages#publish-with-lambda) — in any supported language. Here's a Python example, but you can easily do the same with Go, Ruby, Java, JavaScript, Node.js, .NET, PHP, Rust, C++, the AWS CLI, and more. | ||
|
||
```python | ||
lambda_client.invoke( | ||
FunctionName='Hotsock-PublishFunction-AAABBBCCCDDD', | ||
Payload=json.dumps({ | ||
'channel': 'my-channel', | ||
'event': 'my-event', | ||
'data': '👋' | ||
}) | ||
) | ||
``` | ||
|
||
You can also [publish via good ol' HTTP](/docs/server-api/publish-messages#publish-with-http-url) if that's your preference. | ||
|
||
### Subscribe your clients | ||
|
||
For browser-based clients, you can get up and running quickly with [Hotsock JS](https://github.com/hotsock/hotsock-js). | ||
|
||
```js | ||
// Call the handleMessage function when "my-event" events are | ||
// received on the "my-channel" channel. | ||
const channel = hotsock.channels("my-channel") | ||
channel.bind("my-event", handleMessage) | ||
|
||
function handleMessage(messageObj) { | ||
console.log("Received", messageObj) | ||
} | ||
|
||
// Received Object { | ||
// id: "01HP8BGSHWY952BXW1PE25DSJA", | ||
// event: "my-event", | ||
// channel: "my-channel", | ||
// data: "👋" | ||
// } | ||
``` | ||
|
||
For mobile applications, consider using [URLSessionWebSocketTask](https://developer.apple.com/documentation/foundation/urlsessionwebsockettask) on iOS/macOS and [javax.websocket](https://docs.oracle.com/javaee/7/api/index.html?javax/websocket/package-summary.html) (Java) or [WebSocket](https://kotlinlang.org/api/latest/jvm/stdlib/org.w3c.dom/-web-socket/) from stdlib (Kotlin) on Android. [Hotsock JS](https://github.com/hotsock/hotsock-js) also supports React Native. Official Hotsock client SDKs for iOS/macOS and Android are on the roadmap for the future. | ||
|
||
### Combining the best of fully-managed with self-hosted | ||
|
||
- If it's fully-managed, isn't the data accessible by another provider? Nope! | ||
- If I have to self-host it, don't I have to allocate time to manage it? Nope! | ||
|
||
**Each installation is backed exclusively by fully-managed AWS services that go to great lengths to keep you data private and encrypted.** These services include API Gateway WebSockets, Lambda, DynamoDB, Simple Queue Service (SQS), EventBridge, Simple Notification Service (SNS), and CloudFormation. | ||
|
||
**There are no servers or containers to manage and no scaling knobs to turn.** AWS billing is completely usage-based, so there's no infrastructure cost if the stack is idle and Hotsock will automatically scale to handle production workloads with millions of connections and billions of messages. | ||
|
||
**Installation requires just two AWS CLI commands, doesn't require a sign up, is fully automated with CloudFormation (infrastructure-as-code), and takes less than 20 minutes.** Updates to Hotsock are fully automated, further reducing any ongoing management burden to your staff. | ||
|
||
### Helper tools and libraries | ||
|
||
Alongside this launch, there are a few other tools and libraries that are now available — | ||
|
||
- [jwt-issuer](https://github.com/hotsock/jwt-issuer): A CloudFormation stack that allows you to use AWS Lambda to issue JWTs backed by a key securely stored in AWS Key Management Service (KMS) or Parameter Store. | ||
- [hotsock-js](https://github.com/hotsock/hotsock-js): A client JS library for WebSocket connections, channel subscriptions, and sending/receiving messages. | ||
- [hotsock-ruby](https://github.com/hotsock/hotsock-ruby): A server library for publishing messages and signing Hotsock JWTs from your Ruby/Rails application. | ||
- [installer-permissions](https://github.com/hotsock/installer-permissions): The CloudFormation template containing the [IAM roles and policies needed](/docs/installation/initial-setup/#installer-permissions-stack) when creating a Hotsock installation. | ||
|
||
### Licensing | ||
|
||
The [Free Tier](/docs/licensing/pricing#free-tier) includes 1 million WebSocket messages per month — **forever**. Upgrade your installation to the [Paid Tier](/docs/licensing/pricing#paid-tier) for production applications needing more messages, multiple AWS accounts and regions, and dedicated support. | ||
|
||
[Give it a try](/docs/installation/initial-setup) today! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
james: | ||
name: James Miller | ||
url: https://github.com/bensie | ||
image_url: https://github.com/bensie.png |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Client Messages | ||
|
||
In addition to publishing messages [server-side](../server-api/publish-messages.mdx), connected WebSocket clients can also publish messages if they're authorized to do so. | ||
|
||
## Publish Permissions | ||
|
||
A connected client can publish messages, but only if they have explicit [`publish`](../connections/claims.mdx#channels.messages.publish) permissions to do so for a given event in a particular channel. | ||
|
||
Let's take a chat room example. Assume each person in the `room.123` channel need to send two types of events - one to indicate to other subscribers that they are typing and another to pass each sent chat message. | ||
|
||
Your token must authorize [`subscribe`](../connections/claims.mdx#channels.subscribe) access to the channel and grant [`publish`](../connections/claims.mdx#channels.messages.publish) access to both the `is-typing` and `chat` events. Setting [`echo`](../connections/claims.mdx#channels.messages.echo) to `true` on `chat` events allows the sender to receive a copy of those messages despite also being the sender. There's no need for the sender to also know that they are typing, so `is-typing` is not echoed. | ||
|
||
```json | ||
{ | ||
"channels": { | ||
"room.123": { | ||
"subscribe": true, | ||
"messages": { | ||
"is-typing": { | ||
"publish": true | ||
}, | ||
"chat": { | ||
"publish": true, | ||
"echo": true | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
On the WebSocket, the client can now send a message when they begin typing. | ||
|
||
``` | ||
> {"channel":"room.123","event":"is-typing"} | ||
``` | ||
|
||
Other members of the channel will receive a copy. All client-initiated messages include the sender `uid` and `umd` in the `meta` attribute. | ||
|
||
``` | ||
< {"id":"01J663WM0781SKS3FDWVV0G884","event":"is-typing","channel":"room.123","data":null,"meta":{"uid":"Jim","umd":null}} | ||
``` | ||
|
||
Similarly the client can publish `chat` messages on the WebSocket. | ||
|
||
``` | ||
> {"channel":"room.123","event":"chat","data":"Hello! I just wanted to say hi ❤️"} | ||
``` | ||
|
||
All channel subscribers will receive a copy of this message. But this one will also send a copy to the sender (because of the [`echo`](../connections/claims.mdx#channels.messages.echo) directive). | ||
|
||
``` | ||
< {"id":"01J664PF9MFZPADFA0N5AJB42R","event":"chat","channel":"room.123","data":"Hello! I just wanted to say hi ❤️","meta":{"uid":"Jim","umd":null}} | ||
``` | ||
|
||
You can see this chat example in action in the [Real-Time Chat](/examples/real-time-chat/) demo. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--- | ||
sidebar_label: Overview | ||
--- | ||
|
||
# Channels Overview | ||
|
||
Your applications can have one or more channels and each of your clients can choose which channels to subscribe to. If a client is subscribed to a particular channel, they will receive all messages sent on that channel. | ||
|
||
**Each channel subscription _must_ be authorized by a claim in the token**. This allows you to use channels to control access to different streams of information. | ||
|
||
For example, you may have a "leaderboard" channel that publishes messages that everyone in the application can see. At the same time, you may have a "game.123" channel that publishes all the events that occur in game ID 123, where only people playing or viewing that particular game can see those messages. | ||
|
||
There is no limit to the number of channels your application can have and channels do not need to be declared ahead of time. When any message is published to a channel, any currently subscribed listeners receive a copy of that message. | ||
|
||
Channel names can be any string between 1 to 128 characters and must not contain asterisks (`*`), hashes (`#`), commas (`,`), spaces, or newline characters. | ||
|
||
## Events | ||
|
||
**Each message published to a channel _must_ contain an event name**. Events allow for logically grouping types of messages sent to the same channel. | ||
|
||
For example, if you have a "game.123" channel, perhaps you'd have "move" and "chat" events. In your handler code for these events, different events on the same channel allow you to maintain predictable message shape for different circumstances in the same context. | ||
|
||
In the end, messages received by a subscriber look something like this. The message `id` is Hotsock-generated. | ||
|
||
```json | ||
{ | ||
"channel": "game.123", | ||
"event": "move", | ||
"id": "01H2BSNHFJXKF2XDFD8KMM36FF", | ||
"data": { "player": "Jack", "from": "B1", "to": "C3" } | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"channel": "game.123", | ||
"event": "chat", | ||
"id": "01H2C4Z3PFFJR6RG5D6A12HM92", | ||
"data": "Jack: Good game!" | ||
} | ||
``` | ||
|
||
Your application will receive these messages on the same channel, but can handle "chat" messages differently from "move" messages without a separate channel subscription. | ||
|
||
:::tip When should you use a different channel instead of a different event? | ||
Use channels to filter the data a client needs. All events published to a channel are received by each subscriber, regardless of whether or not the client cares about every event. | ||
|
||
Avoid scenarios where you're sending lots of events to clients where most clients are ignoring those events. | ||
|
||
In these cases, it may be best to move those events to a separate channel and have clients that care about those events subscribe an additional channel. | ||
::: | ||
|
||
## Channel Types | ||
|
||
There are 2 types of channels: [standard](./standard.mdx) and [presence](./presence.mdx). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Presence Channels | ||
|
||
Presence channels build on [standard channels](./standard.mdx) by allowing all subscribers to know information (ID and a custom data payload) about all other subscribers as they join and leave the channel. | ||
|
||
It's great for things like chat rooms and document collaboration, where everyone there can be made aware of who else is present. | ||
|
||
Each member in a presence channel has a `uid` field to identify the user and a `umd` field to supply additional data specific to this user. These attributes are supplied by authentication or subscription token claims ([`uid`](../connections/claims.mdx#uid) and [`umd`](../connections/claims.mdx#umd)) and shared with all other members of the channel. | ||
|
||
:::tip | ||
Presence channel names must have a `presence.` prefix. | ||
::: | ||
|
||
## Limits | ||
|
||
Whenever someone leaves or joins a presence channel, all members of the channel receive a message containing the `uid` and `umd` of all other members. | ||
|
||
**There is no fixed user count limit on presence channels, but the sum total size of all subscribed member payloads (`{"uid":"...","umd":"..."}`) must not exceed 100KB.** Attempting to subscribe to a presence channel that would put the subscriber over this limit will fail with a `PRESENCE_CHANNEL_CAPACITY_REACHED` WebSocket error. | ||
|
||
For example, a presence channel could hold ~100 users with 1KB of user data each or ~800 users with 200 bytes of user data each. | ||
|
||
## Subscribe | ||
|
||
Once connected to the WebSocket with a token authorizing subscribe on the `presence.live-chat` channel, subscribe by sending a message on the WebSocket. | ||
|
||
``` | ||
> {"event":"hotsock.subscribe", "channel":"presence.live-chat"} | ||
``` | ||
|
||
You'll immediately receive confirmation of the subscription with a `hotsock.subscribed` message. The `data` attribute will indicate that you're the only subscriber. | ||
|
||
``` | ||
< {"event":"hotsock.subscribed","channel":"presence.live-chat","data":{"members":[{"uid":"Jim","umd":null}]},"meta":{"uid":"Jim","umd":null}} | ||
``` | ||
|
||
Let's say Dwight joins the channel from another connection. Dwight will receive a `hotsock.subscribed` message similar to the one you received above, but it will indicate that both you and him are present in the channel. | ||
|
||
You will receive a `hotsock.memberAdded` message. The `data` attribute contains the `member` who was just added (Dwight) and a list (array) of all current members (you and Dwight). | ||
|
||
``` | ||
< {"event":"hotsock.memberAdded","channel":"presence.live-chat","data":{"member":{"uid":"Dwight","umd":null},"members":[{"uid":"Jim","umd":null},{"uid":"Dwight","umd":null}]}} | ||
``` | ||
|
||
Here the `member` who was added was Dwight and `members` now contains both of you. | ||
|
||
If Dwight unsubscribes from the channel, you'll receive a `hotsock.memberRemoved` message. | ||
|
||
``` | ||
{"event":"hotsock.memberRemoved","channel":"presence.live-chat","data":{"member":{"uid":"Dwight","umd":null},"members":[{"uid":"Jim","umd":null}]}} | ||
``` | ||
|
||
Here the `member` who was removed was Dwight and `members` no longer includes him. | ||
|
||
If you're subscribing and responding to messages using client-side JS, take a look at [hotsock-js](https://www.github.com/hotsock/hotsock-js) where all of the above is handled by the library. | ||
|
||
## Unsubscribe | ||
|
||
To unsubscribe from a channel, send a `hotsock.unsubscribe` message on the WebSocket. | ||
|
||
``` | ||
> {"event":"hotsock.unsubscribe", "channel":"presence.live-chat"} | ||
``` | ||
|
||
Other members of the presence channel will receive a `hotsock.memberRemoved` message indicating that you left, if anyone else is still present. | ||
|
||
When disconnecting the WebSocket connection, `hotsock.unsubscribe` is called automatically on your behalf for any subscribed channels, notifying anyone still present that you've left. |
Oops, something went wrong.