CloudChatMC

Quick rating

Community listing page, reviews here may not be monitored by the author.

CloudChatMC

No reviews yet

Chat with friends across any Minecraft server — no plugins needed. Powered by a free Cloudflare Worker backend with token-based identity, global chat, and private messaging.

Tech
QoL & Tweaks
Mod Loaders
Fabric
Minecraft

Community voices

Reviews

List view
Grid view
Compact view
Sort by
Date
Rating
Helpful
Unhelpful
Edited
Sort ascending
Show per page
10
25
50
Delete this review?

This removes your review from the project. You can write a new review after.

Review submitted for moderation

Your review has been sent to moderators, who will check that it meets our guidelines before it appears publicly.

No reviews yet. Be the first to review this project!

Get it on

Available Platforms

Compatibility

Supported Environments

Where It Runs
Client Only

Runs entirely on the client. Works on vanilla servers.

About

Project Details

Type
Mod
License
GNU General Public License v3.0 only
Latest Version
CloudChatMC 1.0.0

For authors

Embed Badge

If you're the author of this project, you can embed a live badge anywhere that supports HTML or Markdown. It updates automatically whenever ratings change.

Custom banner text
ModDex rating badge preview

Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.

Identifiers

Platform IDs

CurseForge ID
Modrinth ID

Resources

External Links

About

Description

CloudChatMC

Source Code Issues Modrinth CurseForge

CloudChatMC is a client-side Fabric mod that creates a private, persistent chat tunnel between you and your friends — completely independent of whatever Minecraft server you're all playing on.

Whether you're on different servers, different worlds, or one of you is in singleplayer, CloudChatMC keeps you connected through a free Cloudflare Worker backend.

Features

  • Global chat — Send messages to all connected friends at once
  • Private messaging — Send direct messages to specific players
  • Online tracking — See who's currently connected with /ccmc online
  • Token-based identity — Each player has a unique token, no login needed
  • Encrypted messages — All messages are encoded before sending
  • Auto-reconnect — Automatically reconnects if the connection drops
  • Message queueing — Messages received during game load are not lost
  • Config command — Update your token and server URL in-game without restarting

Commands

Command Description
/ccmc msg <message> Send a global message to all connected players
/ccmc pm <player> <message> Send a private message to a specific player
/ccmc online Show all currently connected players
/ccmc status Show your current connection status
/ccmc config <token> <url> Update token and WebSocket URL at runtime
/ccmc help Show all available commands

Setup

CloudChatMC requires a Cloudflare Worker backend to relay messages. Follow the steps below to host your own — it's completely free.


Step 1 — Create a Cloudflare Worker

  1. Go to Cloudflare Dashboard and sign up for free
  2. Go to Workers & Pages → Create
  3. Create a new Worker with any name (e.g. cloudchatmc)

Step 2 — Set up Wrangler CLI

npm install -g wrangler
wrangler login
mkdir cloudchatmc-worker
cd cloudchatmc-worker

Step 3 — Create wrangler.toml

name = "your-worker-name"
main = "worker.js"
compatibility_date = "2024-01-01"

[[durable_objects.bindings]]
name = "CHAT_ROOM"
class_name = "ChatRoom"

[[migrations]]
tag = "v1"
new_sqlite_classes = ["ChatRoom"]

Replace your-worker-name with the name you gave your Worker.


Step 4 — Create worker.js

// Add your tokens and player names here
// Format: "TOKEN": "PlayerName"
// Generate strong random tokens — avoid special characters
// Example: use alphanumeric strings of 32+ characters
const TOKENS = {
  "token_for_player1": "Player1",
  "token_for_player2": "Player2",
  "token_for_player3": "Player3",
  "token_for_admin":   "Admin"
};

export class ChatRoom {
  constructor(state, env) {
    this.clients = new Map();
  }

  async fetch(request) {
    if (request.headers.get("Upgrade") !== "websocket") {
      return new Response("WebSocket only", { status: 400 });
    }

    const url = new URL(request.url);
    const token = url.searchParams.get("token");

    if (!token || !TOKENS[token]) {
      return new Response("Unauthorized", { status: 401 });
    }

    const username = TOKENS[token];

    const existing = this.clients.get(username);
    if (existing) {
      try { existing.close(1000, "Replaced by new connection"); } catch {}
      this.clients.delete(username);
    }

    const [client, server] = new WebSocketPair();
    server.accept();

    this.clients.set(username, server);
    this.broadcast({ type: "join", user: username });

    server.addEventListener("message", (event) => {
      let data;
      try {
        data = JSON.parse(event.data);
      } catch {
        return;
      }

      if (data.type === "broadcast") {
        this.broadcast({ type: "msg", from: username, data: data.data });

      } else if (data.type === "private") {
        const target = this.clients.get(data.to);
        if (target) {
          try {
            target.send(JSON.stringify({
              type: "pm",
              from: username,
              data: data.data
            }));
          } catch {
            this.clients.delete(data.to);
            this.safeSend(server, { type: "error", message: "Player not online" });
          }
        } else {
          this.safeSend(server, { type: "error", message: "Player not online" });
        }

      } else if (data.type === "list") {
        this.safeSend(server, {
          type: "list",
          users: [...this.clients.keys()]
        });
      }
    });

    server.addEventListener("close", () => {
      this.clients.delete(username);
      this.broadcast({ type: "leave", user: username });
    });

    server.addEventListener("error", () => {
      this.clients.delete(username);
    });

    return new Response(null, { status: 101, webSocket: client });
  }

  broadcast(obj) {
    const msg = JSON.stringify(obj);
    const dead = [];
    for (const [name, ws] of this.clients) {
      try {
        ws.send(msg);
      } catch {
        dead.push(name);
      }
    }
    for (const name of dead) this.clients.delete(name);
  }

  safeSend(ws, obj) {
    try { ws.send(JSON.stringify(obj)); } catch {}
  }
}

export default {
  async fetch(request, env) {
    if (request.headers.get("Upgrade") !== "websocket") {
      return new Response("WebSocket only", { status: 400 });
    }

    const url = new URL(request.url);
    const token = url.searchParams.get("token");

    if (!token || !TOKENS[token]) {
      return new Response("Unauthorized", { status: 401 });
    }

    const id = env.CHAT_ROOM.idFromName("global");
    const room = env.CHAT_ROOM.get(id);
    return room.fetch(request);
  }
};

Step 5 — Deploy

wrangler deploy

Your Worker URL will be: wss://your-worker-name.your-subdomain.workers.dev


Step 6 — Configure the mod

Set your token and Worker URL in: .minecraft/config/cloudchatmc.json

{
  "token": "YOUR_TOKEN_HERE",
  "url": "wss://your-worker-name.your-subdomain.workers.dev"
}

Or use the in-game command:

/ccmc config YOUR_TOKEN wss://your-worker-name.your-subdomain.workers.dev

Token Tips

  • Each player gets their own unique token — never share tokens between players
  • Use long alphanumeric strings (32+ characters) with no special characters
  • Keep tokens private — anyone with a token can connect as that player
  • You can generate safe tokens at String Generator

Requirements

  • Minecraft 1.21.4-1.21.11
  • Fabric Loader 0.16.10+
  • Fabric API

Why CloudChatMC?

Most cross-server communication mods require a dedicated server or paid hosting. CloudChatMC uses Cloudflare Workers with Durable Objects which has a generous free tier — making it completely free to run for small friend groups with no maintenance required.

License

GPL-3.0 — free to use, modify, and distribute.

CloudChatMC

Source Code Issues Modrinth CurseForge

CloudChatMC is a client-side Fabric mod that creates a private, persistent chat tunnel between you and your friends — completely independent of whatever Minecraft server you're all playing on.

Whether you're on different servers, different worlds, or one of you is in singleplayer, CloudChatMC keeps you connected through a free Cloudflare Worker backend.

Features

  • Global chat — Send messages to all connected friends at once
  • Private messaging — Send direct messages to specific players
  • Online tracking — See who's currently connected with /ccmc online
  • Token-based identity — Each player has a unique token, no login needed
  • Encrypted messages — All messages are encoded before sending
  • Auto-reconnect — Automatically reconnects if the connection drops
  • Message queueing — Messages received during game load are not lost
  • Config command — Update your token and server URL in-game without restarting

Commands

Command Description
/ccmc msg <message> Send a global message to all connected players
/ccmc pm <player> <message> Send a private message to a specific player
/ccmc online Show all currently connected players
/ccmc status Show your current connection status
/ccmc config <token> <url> Update token and WebSocket URL at runtime
/ccmc help Show all available commands

Setup

CloudChatMC requires a Cloudflare Worker backend to relay messages. Follow the steps below to host your own — it's completely free.


Step 1 — Create a Cloudflare Worker

  1. Go to Cloudflare Dashboard and sign up for free
  2. Go to Workers & Pages → Create
  3. Create a new Worker with any name (e.g. cloudchatmc)

Step 2 — Set up Wrangler CLI

npm install -g wrangler
wrangler login
mkdir cloudchatmc-worker
cd cloudchatmc-worker

Step 3 — Create wrangler.toml

name = "your-worker-name"
main = "worker.js"
compatibility_date = "2024-01-01"

[[durable_objects.bindings]]
name = "CHAT_ROOM"
class_name = "ChatRoom"

[[migrations]]
tag = "v1"
new_sqlite_classes = ["ChatRoom"]

Replace your-worker-name with the name you gave your Worker.


Step 4 — Create worker.js

// Add your tokens and player names here
// Format: "TOKEN": "PlayerName"
// Generate strong random tokens — avoid special characters
// Example: use alphanumeric strings of 32+ characters
const TOKENS = {
  "token_for_player1": "Player1",
  "token_for_player2": "Player2",
  "token_for_player3": "Player3",
  "token_for_admin":   "Admin"
};

export class ChatRoom {
  constructor(state, env) {
    this.clients = new Map();
  }

  async fetch(request) {
    if (request.headers.get("Upgrade") !== "websocket") {
      return new Response("WebSocket only", { status: 400 });
    }

    const url = new URL(request.url);
    const token = url.searchParams.get("token");

    if (!token || !TOKENS[token]) {
      return new Response("Unauthorized", { status: 401 });
    }

    const username = TOKENS[token];

    const existing = this.clients.get(username);
    if (existing) {
      try { existing.close(1000, "Replaced by new connection"); } catch {}
      this.clients.delete(username);
    }

    const [client, server] = new WebSocketPair();
    server.accept();

    this.clients.set(username, server);
    this.broadcast({ type: "join", user: username });

    server.addEventListener("message", (event) => {
      let data;
      try {
        data = JSON.parse(event.data);
      } catch {
        return;
      }

      if (data.type === "broadcast") {
        this.broadcast({ type: "msg", from: username, data: data.data });

      } else if (data.type === "private") {
        const target = this.clients.get(data.to);
        if (target) {
          try {
            target.send(JSON.stringify({
              type: "pm",
              from: username,
              data: data.data
            }));
          } catch {
            this.clients.delete(data.to);
            this.safeSend(server, { type: "error", message: "Player not online" });
          }
        } else {
          this.safeSend(server, { type: "error", message: "Player not online" });
        }

      } else if (data.type === "list") {
        this.safeSend(server, {
          type: "list",
          users: [...this.clients.keys()]
        });
      }
    });

    server.addEventListener("close", () => {
      this.clients.delete(username);
      this.broadcast({ type: "leave", user: username });
    });

    server.addEventListener("error", () => {
      this.clients.delete(username);
    });

    return new Response(null, { status: 101, webSocket: client });
  }

  broadcast(obj) {
    const msg = JSON.stringify(obj);
    const dead = [];
    for (const [name, ws] of this.clients) {
      try {
        ws.send(msg);
      } catch {
        dead.push(name);
      }
    }
    for (const name of dead) this.clients.delete(name);
  }

  safeSend(ws, obj) {
    try { ws.send(JSON.stringify(obj)); } catch {}
  }
}

export default {
  async fetch(request, env) {
    if (request.headers.get("Upgrade") !== "websocket") {
      return new Response("WebSocket only", { status: 400 });
    }

    const url = new URL(request.url);
    const token = url.searchParams.get("token");

    if (!token || !TOKENS[token]) {
      return new Response("Unauthorized", { status: 401 });
    }

    const id = env.CHAT_ROOM.idFromName("global");
    const room = env.CHAT_ROOM.get(id);
    return room.fetch(request);
  }
};

Step 5 — Deploy

wrangler deploy

Your Worker URL will be: wss://your-worker-name.your-subdomain.workers.dev


Step 6 — Configure the mod

Set your token and Worker URL in: .minecraft/config/cloudchatmc.json

{
  "token": "YOUR_TOKEN_HERE",
  "url": "wss://your-worker-name.your-subdomain.workers.dev"
}

Or use the in-game command:

/ccmc config YOUR_TOKEN wss://your-worker-name.your-subdomain.workers.dev

Token Tips

  • Each player gets their own unique token — never share tokens between players
  • Use long alphanumeric strings (32+ characters) with no special characters
  • Keep tokens private — anyone with a token can connect as that player
  • You can generate safe tokens at String Generator

Requirements

  • Minecraft 1.21.4-1.21.11
  • Fabric Loader 0.16.10+
  • Fabric API

Why CloudChatMC?

Most cross-server communication mods require a dedicated server or paid hosting. CloudChatMC uses Cloudflare Workers with Durable Objects which has a generous free tier — making it completely free to run for small friend groups with no maintenance required.

License

GPL-3.0 — free to use, modify, and distribute.

Screenshots

Gallery

This project has no gallery images yet.

Versions

Files

Relations

Project Relations

More like this

Similar Mods

Suggestions use data such as tags, dependencies, dependents, descriptions, titles, and more to rank how much they overlap with this mod.

On ModDex

Community snapshot

0
Ratings
0
Followers
0
In stacks

By the numbers

Statistics

<1,000
Total Downloads
CurseForge
<1,000
Modrinth
<1,000
Last Updated
CurseForge
Created
CurseForge
Modrinth
Last synced
When ModDex last fetched this project from CurseForge or Modrinth. Every project is re-checked on a schedule, and any project that ships a new file is synced automatically within hours of the release.
New file updates sync automatically
How syncing works