Advanced

Como Construir um Sistema de Notificacao com Claude Code

Aprenda a build a notification system usando o Claude Code. Inclui exemplos praticos de codigo e orientacao passo a passo.

通知システムの構築をClaude Codeで効率化する

Webアプリにおける通知は、トースト表示からプッシュ通知、リアルタイム更新まで多岐にわたります。Claude Codeを使えば、これらを統合した通知基盤を短時間で構築できます。

トースト通知コンポーネントの実装

まずはアプリ内で使うトースト通知を作ります。

> ライブラリを使わずにトースト通知コンポーネントをReactで作って。
> success/error/warning/infoの4種類。自動で消える。スタック表示対応。
import { createContext, useContext, useState, useCallback, type ReactNode } from "react";

type ToastType = "success" | "error" | "warning" | "info";

interface Toast {
  id: string;
  type: ToastType;
  message: string;
}

interface ToastContextType {
  addToast: (type: ToastType, message: string) => void;
}

const ToastContext = createContext<ToastContextType | null>(null);

const TOAST_STYLES: Record<ToastType, string> = {
  success: "bg-green-500 text-white",
  error: "bg-red-500 text-white",
  warning: "bg-yellow-500 text-black",
  info: "bg-blue-500 text-white",
};

const TOAST_ICONS: Record<ToastType, string> = {
  success: "✓",
  error: "✕",
  warning: "⚠",
  info: "ℹ",
};

export function ToastProvider({ children }: { children: ReactNode }) {
  const [toasts, setToasts] = useState<Toast[]>([]);

  const addToast = useCallback((type: ToastType, message: string) => {
    const id = crypto.randomUUID();
    setToasts((prev) => [...prev, { id, type, message }]);

    setTimeout(() => {
      setToasts((prev) => prev.filter((t) => t.id !== id));
    }, 4000);
  }, []);

  return (
    <ToastContext.Provider value={{ addToast }}>
      {children}
      <div className="fixed bottom-4 right-4 flex flex-col gap-2 z-50">
        {toasts.map((toast) => (
          <div
            key={toast.id}
            className={`px-4 py-3 rounded-lg shadow-lg flex items-center gap-2 animate-slide-in ${TOAST_STYLES[toast.type]}`}
          >
            <span>{TOAST_ICONS[toast.type]}</span>
            <span>{toast.message}</span>
            <button
              onClick={() => setToasts((prev) => prev.filter((t) => t.id !== toast.id))}
              className="ml-2 opacity-70 hover:opacity-100"
            >

            </button>
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

export function useToast() {
  const context = useContext(ToastContext);
  if (!context) throw new Error("useToast must be used within ToastProvider");
  return context;
}

WebSocketによるリアルタイム通知

サーバーからのリアルタイム通知を受け取る仕組みも構築できます。

// Server side(Node.js + ws)
import { WebSocketServer, WebSocket } from "ws";

interface Client {
  ws: WebSocket;
  userId: string;
}

const clients: Client[] = [];

const wss = new WebSocketServer({ port: 8080 });

wss.on("connection", (ws, req) => {
  const userId = new URL(req.url!, `http://${req.headers.host}`).searchParams.get("userId");
  if (!userId) return ws.close();

  clients.push({ ws, userId });

  ws.on("close", () => {
    const index = clients.findIndex((c) => c.ws === ws);
    if (index !== -1) clients.splice(index, 1);
  });
});

// 特定ユーザーへの通知送信
export function sendNotification(userId: string, notification: object) {
  clients
    .filter((c) => c.userId === userId)
    .forEach((c) => c.ws.send(JSON.stringify(notification)));
}
// Client sideのフック
import { useEffect, useRef, useCallback } from "react";

interface Notification {
  id: string;
  type: string;
  title: string;
  body: string;
}

export function useNotifications(userId: string, onNotification: (n: Notification) => void) {
  const wsRef = useRef<WebSocket | null>(null);

  const connect = useCallback(() => {
    const ws = new WebSocket(`ws://localhost:8080?userId=${userId}`);

    ws.onmessage = (event) => {
      const notification = JSON.parse(event.data);
      onNotification(notification);
    };

    ws.onclose = () => {
      setTimeout(connect, 3000); // Reconnect
    };

    wsRef.current = ws;
  }, [userId, onNotification]);

  useEffect(() => {
    connect();
    return () => wsRef.current?.close();
  }, [connect]);
}

通知の永続化と既読管理

通知をDBに保存して既読管理する機能も追加できます。

// Prismaスキーマから自動でAPI生成を依頼
// schema.prisma の内容をClaude Codeが読み取って実装
import { db } from "@/lib/database";

export async function getNotifications(userId: string) {
  return db.notification.findMany({
    where: { userId },
    orderBy: { createdAt: "desc" },
    take: 50,
  });
}

export async function markAsRead(notificationId: string) {
  return db.notification.update({
    where: { id: notificationId },
    data: { readAt: new Date() },
  });
}

export async function getUnreadCount(userId: string) {
  return db.notification.count({
    where: { userId, readAt: null },
  });
}

Claude Codeでの開発効率を上げるには生産性を3倍にする10のTipsを参考にしてください。フォームとの連携についてはフォームバリデーション設計も併せてご覧ください。

Summary

Claude Codeを使えば、トースト通知、リアルタイム通知、永続化まで含めた通知システム全体を効率的に構築できます。自然言語で要件を伝え、段階的に機能を追加していくのがおすすめです。

公式ドキュメントはClaude Codeから確認できます。

#Claude Code #notification system #WebSocket #toast #real-time