> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fly.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat: A 6PN Example with NATS

<Warning>
  **Warning: This document is old! It is likely wrong in some important way.**
</Warning>

# 6pn-demo-chat

A chat server that uses Fly 6PN networking to connect to a NATS cluster enabling global chat.

## Rationale

This is the code for a very simple chat example that uses bare websockets in Node and a Browser to connect to it.

Instead of immediately broadcasting the message to all users, the server sends the message on to a NATS server, using 6PN private networking, which broadcasts the message to all interested parties.

## Preparation

As this example relies on a NATS server (or cluster) to be available, it should be deployed alongside the [`nats-cluster`](https://github.com/fly-examples/nats-cluster) example, within the same Fly organization.

Make a note of the app-name used to deploy the NATS cluster.

Select a name for your chat app.

## Initializing

Create an app on Fly with your chosen chat app name, using `fly init`:

```bash theme={null}
fly init YOURAPPNAME --import example-fly.toml
```

## Deploying

To deploy this app, we have one detail we have to pass it, the name fo the NATS cluster. The Dockerfile we use takes a build argument (NATSAPP) and turns it into an environment variable for the app to pick up when it runs. So if your NATS cluster app is called `myclusterapp` then running:

```bash theme={null}
fly deploy --build-arg NATSAPP=myclusterapp
```

Note: You can make that setting permanent by adding

```toml theme={null}
[build.args]
   NATSAPP="myclusterapp"
```

to the fly.toml file.

Once deployed, open up the web page - `fly open` will get you there quickly - enter a chat handle and begin chatting.

## Notes

The more interesting parts of this app happen out of sight of the users. It's worth following the path of the NATSAPP build argument to find out more.

* NATSAPP's value is passed as a build argument to the Dockerfile at deployment time.
* Inside the Dockerfile, the build argument is converted into an Environment variable, `NATSAPPHOST` which is retained with the image's configuration.
* When the `server.js` app starts up, it picks up the `NATSAPPHOST` variable:

```
let natsapphost=process.env.NATSAPPHOST
```

* It then uses that value to connect to the NATS cluster:

```
const nc = NATS.connect(natsapphost+".internal");
```

The combination of an app name and `.internal` in 6PN networking resolves to the IPV6 addresses of the first instance of all instances if that app currently running. So, if we set NATSAPP to `myclusterapp` then scaling and adding nodes to `myclusterapp` would automatically be reflected in `myclusterapp.internal`. 6PN has a number of `.internal` addresses an app can query which you can read about in the [6PN documentation](/networking/services#internal-addresses).

Once the chat server has connected to the NATS cluster, it subscribes to a topic `msg` and any message written to `msg` will be broadcast to all web socket clients that are connected. If any of those web socket clients sends a message to the chat server, then it will publish that message to the `msg` topic on the NATs cluster. It doesn't even try to echo it locally, relying on the NATS cluster to publish to subscribers.

The NATS cluster can be scaled up and down according to demand. Chat servers will always be able to locate an available node thanks to Fly 6PN networking advertising homogenous services through DNS and `.internal` addresses. You can then deploy the NATS cluster and/or the chat server to any region and know that both will have predictable names; the NATS cluster through Fly's 6PN networking, and the chat server through Fly's AnyCast Edge network.

## Discuss

You can discuss this example (and the nats-cluster example) on the [dedicated Fly Community topic](https://community.fly.io/t/new-examples-nats-cluster-and-6pn-demo-chat/562).
