DEV Community

Alex Spinov
Alex Spinov

Posted on

PartyKit Has a Free API That Makes Real-Time Multiplayer Apps Simple

PartyKit is the platform for real-time, multiplayer, and AI applications. Build collaborative features with WebSockets, state machines, and AI in minutes.

Party Server: Stateful WebSocket

// party/main.ts
import type { Party, Connection, ConnectionContext } from "partykit/server";

export default class ScrapingRoom implements Party.Server {
  connections: Map<string, Connection> = new Map();
  products: Product[] = [];

  onConnect(conn: Connection, ctx: ConnectionContext) {
    // Send current state to new connection
    conn.send(JSON.stringify({ type: "init", products: this.products }));
  }

  onMessage(message: string, sender: Connection) {
    const data = JSON.parse(message);

    switch (data.type) {
      case "add-product":
        this.products.push(data.product);
        // Broadcast to ALL connected clients
        this.room.broadcast(JSON.stringify({
          type: "product-added",
          product: data.product,
        }));
        break;

      case "update-price":
        const product = this.products.find(p => p.id === data.id);
        if (product) product.price = data.price;
        this.room.broadcast(JSON.stringify({
          type: "price-updated",
          id: data.id,
          price: data.price,
        }));
        break;
    }
  }

  onClose(conn: Connection) {
    this.connections.delete(conn.id);
  }
}
Enter fullscreen mode Exit fullscreen mode

Client: Connect and Collaborate

import PartySocket from "partysocket";

const ws = new PartySocket({
  host: "my-project.username.partykit.dev",
  room: "scraping-dashboard",
});

ws.addEventListener("message", (event) => {
  const data = JSON.parse(event.data);
  switch (data.type) {
    case "init": setProducts(data.products); break;
    case "product-added": addProduct(data.product); break;
    case "price-updated": updatePrice(data.id, data.price); break;
  }
});

// Send updates
ws.send(JSON.stringify({
  type: "add-product",
  product: { id: "123", title: "Widget", price: 29.99 },
}));
Enter fullscreen mode Exit fullscreen mode

React Hook

import usePartySocket from "partysocket/react";

function Dashboard() {
  const [products, setProducts] = useState([]);

  const ws = usePartySocket({
    host: "my-project.username.partykit.dev",
    room: "dashboard",
    onMessage(event) {
      const data = JSON.parse(event.data);
      if (data.type === "init") setProducts(data.products);
      if (data.type === "product-added") setProducts(prev => [...prev, data.product]);
    },
  });

  return products.map(p => <ProductCard key={p.id} product={p} />);
}
Enter fullscreen mode Exit fullscreen mode

Cron and Alarms

export default class ScrapingScheduler implements Party.Server {
  async onAlarm() {
    // Runs on schedule
    const products = await scrapeProducts();
    this.room.broadcast(JSON.stringify({ type: "scraped", products }));

    // Schedule next alarm
    this.room.storage.setAlarm(Date.now() + 60 * 60 * 1000); // 1 hour
  }

  onConnect() {
    // Start scheduling on first connection
    this.room.storage.setAlarm(Date.now() + 1000);
  }
}
Enter fullscreen mode Exit fullscreen mode

AI Integration

import { AI } from "partykit/ai";

export default class AIRoom implements Party.Server {
  ai = new AI(this.room);

  async onMessage(message: string) {
    const response = await this.ai.run("@cf/meta/llama-3-8b-instruct", {
      messages: [{ role: "user", content: message }],
    });
    this.room.broadcast(JSON.stringify({ type: "ai-response", text: response }));
  }
}
Enter fullscreen mode Exit fullscreen mode

Build collaborative data apps? My Apify tools + PartyKit = real-time team dashboards.

Custom real-time solution? Email spinov001@gmail.com

Top comments (0)