0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vercel Postgresで匿名コメント欄を実装する(Next.js App Router)

Posted at

なにを作ったか

  • 認証なし(表示名+任意ID)でコメント投稿
  • 保存先は Vercel Postgres@vercel/postgres
  • APIは Next.js App Router の Route Handlers/api/comments
  • 最低限の対策(IPハッシュのレート制限, honeypot, 本文最大長, XSS回避)
  • blog / portfolio 両ページにコメント一覧+投稿フォームを組み込み

データモデル

テーブル comments を用意。アプリ側で UUID を発行するため、DB拡張は不要です。

create table if not exists comments (
  id uuid primary key,
  site text not null,           -- 'blog' | 'portfolio'
  slug text not null,
  user_display_name text not null,
  user_public_id text not null,
  content text not null,
  created_at timestamptz not null default now(),
  ip_hash text,
  is_approved boolean not null default true,
  parent_id uuid references comments(id)
);
create index if not exists idx_comments_site_slug_created_at on comments(site, slug, created_at desc);

APIのポイント

  • GET /api/comments?site=blog|portfolio&slug=...:承認済みのみ返却
  • POST /api/comments:本文バリデーション・honeypot・レート制限を適用
  • PATCH/DELETE /api/comments/[id]Authorization: Bearer COMMENT_ADMIN_TOKEN 必須

実装では randomUUID()id を作り、IPは sha256(ip + SALT) によるハッシュのみ保存します。


UI(CommentSection

  • 表示名 / ユーザーID / 本文 / 同意チェック
  • 送信後に一覧を再取得
  • スタイルは既存UIのボタンコンポーネントを利用

環境変数

.env / Vercel:

POSTGRES_URL=postgres://USER:PASSWORD@HOST:PORT/DB
COMMENT_ADMIN_TOKEN=長いランダム値
COMMENT_HASH_SALT=長いランダム値
COMMENT_RATE_LIMIT_PER_MIN=3
COMMENT_MAX_LENGTH=1000

まとめ

シンプルな要件でも「悪用されにくい設計」にすることで、運用負荷を抑えられます。今後はスレッド/返信、モデレーションUI、エクスポートなどに拡張予定です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?