- Discordクローン作成 1. 環境構築〜Clerkの設定 👈ココ
- Discordクローン作成 2. ダークモード〜Prisma, PlanetScale
- Discordクローン作成 3. モーダルUI, 画像(uploadthing)
- Discordクローン作成 4. サーバ作成, ナビゲーション
- Discordクローン作成 5. サーバー作成用モーダル、サイドバー作成
- Discordクローン作成 7. メンバーの管理
- Discordクローン作成 8. チャンネル作成、サーバ削除・退出
- Discordクローン作成 9. サーバ検索、チャンネルリスト
- Discordクローン作成 10. チャンネルページ作成
- Discordクローン作成 11. 会話ページ作成
- Discordクローン作成 12. メッセージ送信
- Discordクローン作成 13. リアルタイムチャット
1. 環境構築
環境構築
shadcn/ui を利用する。手順は公式にしたがう。

Next.jsプロジェクトの作成
pnpm create next-app@latest discord-clone --typescript --tailwind --eslint
作成したらプロジェクト内に移動する。
cd discord-clone
shadcn/uiのインストール
pnpm dlx shadcn-ui@latest init
√ Which style would you like to use? » Default
√ Which color would you like to use as base color? » Stone
√ Would you like to use CSS variables for colors? ... no / yes
設定に応じたファイルが生成される。
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "stone",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
初期セットアップ
cssの設定
高さの設定を行う。
@tailwind base;
@tailwind components;
@tailwind utilities;
html,
body :root {
height: 100%;
}
pageの初期化
export default function Home() {
return (
<p className="text-3xl font-bold text-indigo-500">Hello Discord Clone</p>
);
}
Tailwindの補完を入れていない場合は以下を導入しておく
ボタンコンポーネントの作成
https://ui.shadcn.com/docs/components/button
shadcn/uiのボタンコンポーネントを利用する。
コンポーネントは作成するタイミングで components.json
の設定を読み込み、設定に従った初期ファイルが生成される。
pnpm dlx shadcn-ui@latest add button
components\ui\button.tsx
が生成される。ファイルの中身はtailwindベースでカスタマイズが可能となっているので、必要に応じて修正することができる。
cnライブラリについて
shadcn/uiのコンポーネントを追加すると以下のライブラリも合わせて追加される
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
これはshadcn/uiのコンポーネントを利用する際に必要となるライブラリで、tailwindのクラスを結合してくれる。
<Button className={cn("bg-indigo-500", state && "bg-red-500")}>
Click me
</Button>
上記の例では、stateがtrueの場合に bg-red-500
が適用される。このような使い方ができるのが特徴。
2. ページ設定
フォントの設定
Open Sansに変更を行う。
import type { Metadata } from "next";
import { Open_Sans } from "next/font/google";
import "./globals.css";
const font = Open_Sans({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Team Chat App",
description: "dicord clone",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={font.className}>{children}</body>
</html>
);
}
フォルダ設定について
()を利用したフォルダ設定
Next.js では()を利用することでルーティングに影響しない形でフォルダを設定することができる。
const LoginPage = () => {
return <div>LoginPage</div>;
};
export default LoginPage;
http://localhost:3000/login でアクセスできる。
layoutの設定
フォルダを切り分けることでlayoutも制御することができる。
const AuthLayout = ({ children }: { children: React.ReactNode }) => {
return <div className="bg-red-500">{children}</div>;
};
export default AuthLayout;
3. 認証
Clerkの導入
Clerkは認証周りの機能を提供してくれるサービスです。Clerkを使うことで、認証周りの実装を簡単に行うことができます。 NextAuth(Auth.js)を使う選択肢もあります。

Clerkにログインする
アプリケーションを作成する
クイックスタートにNext.jsへの取り込み方が表示される。
.envに追加する
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_
CLERK_SECRET_KEY=sk_test_
プロジェクトにClerkの追加
ドキュメントを確認するとNext.jsでの利用方法が記載されている。
手順に従って追加する
pnpm add @clerk/nextjs
プロバイダをマウントする
layout.tsxにプロバイダをマウントする(手順どおりなので省略)。 Providerって何?というのは useContext のドキュメントを読むと理解が深まるはず。
clerkのミドルウェア設定の作成
デフォルト設定でauthMiddleware()を使用するとすべてのルートで認証が有効になる。 パブリックディレクトリ、認証が必要なディレクトリ等を管理するため、ミドルウェア設定を作成する。 (publicRoutes, ignoredRoutesを設定することで、認証が必要なルートを設定することができる)
import { authMiddleware } from "@clerk/nextjs";
export default authMiddleware({
// Routes that can be accessed while signed out
publicRoutes: ['/anyone-can-visit-this-route'],
// Routes that can always be accessed, and have
// no authentication information
ignoredRoutes: ['/no-auth-in-this-route'],
});
export const config = {
// Protects all routes, including api/trpc.
// See https://clerk.com/docs/references/nextjs/auth-middleware
// for more information about configuring your Middleware
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
サインアップ/サインイン ページの作成
以下ドキュメントの手順に従って準備 https://clerk.com/docs/references/nextjs/custom-signup-signin-pages
サインアップ
import { SignUp } from "@clerk/nextjs";
export default function Page() {
return <SignUp />;
}
サインイン
import { SignIn } from "@clerk/nextjs";
export default function Page() {
return <SignIn />;
}
環境変数に追加
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
画面レイアウト調整
これだけでclerkのログイン画面は表示されるが、画面中央に表示されるように調整する。
const AuthLayout = ({ children }: { children: React.ReactNode }) => {
return (
<div className="h-full flex justify-center items-center">{children}</div>
);
};
export default AuthLayout;
ここまででClerkによるログイン認証が表示されるようになる。
サインアウトボタンの追加
ログイン後にサインアウトできるようにボタンコンポーネントを追加する
import { UserButton } from "@clerk/nextjs";
export default function Home() {
return (
<div className="">
<UserButton />
</div>
);
}
ログアウト後にlocalhostにリダイレクトしないが現時点では正常。再び実行すると正常に動作する。 ※っぽいのだけど、ログアウト後にログイン画面にリダイレクトが動く場合と動かない場合がある。ひとまずそのまま