No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Next.js App Router の教材をベースにした Twitter(X)風アプリ。要件は docs/functions.md、画面遷移は docs/front_design.md を参照。
| 層 | 場所 | 役割 |
|---|---|---|
| shared | shared/ | UUID正規化など業務知識を含まない処理。他の層をimportしない |
| domain | domain/ | entities/(ユーザーの型)、value_objects/(入力ルール・画像の状態)、repository_ifs/(永続化の契約)、external_service_ifs/(パスワードハッシュ・セッション終了・ストレージ・画像検査の契約)。フレームワークやDB、上位層に依存しない |
| application | application/ | usecases/<機能>/(登録・投稿などの処理)、dtos/<機能>/(一覧型・結果型)、query_service_ifs/<機能>/(タイムライン・プロフィール・お気に入りの読み取り契約)。Next.jsや具体実装に依存しない |
| infra | infra/ | persistence/postgres/(接続・マイグレーション・repositories/・query_services/)と external_services/(scrypt・Vercel Blob・sharp)。domain/applicationの契約を実装する |
| main | main/container/ | 具体実装の組み立て(DI)。Web用は機能別ファイルで server-only・遅延初期化、CLI用は cli/ に置き server-only を使わない |
| app | app/ | 画面、Server Action、Route Handler、Auth.js の設定。サーバー側の処理は main/container/ の取得関数だけを呼び、クライアントコンポーネントからは import しない |
DB は Vercel の Storage から作成する Postgres(Neon)を使う。
pnpm dlx vercel link)。POSTGRES_URL などの環境変数が自動で登録される。AUTH_SECRET(openssl rand -base64 32 の値)を追加する。AUTH_URL は Vercel 上では設定しない。pnpm install
pnpm dlx vercel env pull .env.local # POSTGRES_URL などを .env.local に保存
pnpm db:migrate # POSTGRES_URL_NON_POOLING(なければ POSTGRES_URL)に適用
pnpm dev
.env.local が .env より優先される。ローカル専用の AUTH_URL などは .env に書く(.env.example 参照)。vercel env pull で取得するDBは本番と同じ。開発で分けたい場合は Neon で開発用ブランチを作り、その接続URLを .env.development.local の POSTGRES_URL(プール経由)と POSTGRES_URL_NON_POOLING(プールなし)に書く。pnpm dev と pnpm db:migrate はこちらを優先する。twitter に作成する。pnpm db:migrate を実行する。結合テストと E2E はデータを書き込むため、本番・開発とは別の DB を TEST_POSTGRES_URL に指定する。Neon コンソールでテスト用のブランチ(または別の database)を作り、その接続URLを .env に書く。Vercel の環境変数には登録しない。
pnpm db:migrate --test で TEST_POSTGRES_URL 側にも適用できる(テストは自動で適用する)。
| コマンド | 内容 |
|---|---|
pnpm test:unit | domain・ユースケース・Server Action・UI の単体テスト(DB不要) |
pnpm test:integration | 実 PostgreSQL の Repository と実 scrypt のテスト |
pnpm test:e2e | Playwright。テストDBに向けた本番ビルドを port 3100 で起動して検証 |
pnpm typecheck | 型チェック |
TEST_POSTGRES_URL が必須。未設定、またはアプリ用の URL(Neon のプール経由・プールなしを含む)と同じ DB なら実行前に失敗する。pnpm exec playwright install chromium でブラウザを取得する。/login は登録時と同じ形式ルールでID・パスワードを検証してから認証する。形式違反はAuth.jsへの直接リクエストでも認証ユースケースで拒否する。/login は / に移動する。Cookieの有無だけでは判断しない。twitter.tweets)・フォロー(twitter.follows)・リツイート(twitter.retweets)は 002-create-timeline.sql で作成する。利用者を削除すると関連行もcascadeで削除される。(出来事の日時, 種類, ID) のキーセットで20件ずつページングする。OFFSETは使わない。timestamptz 型のパラメータを Date(ミリ秒)に変換するため、SQLでは ::text::timestamptz で渡している。test/support/timeline-fixtures.ts)。/profile/{ユーザーID} は未ログインでも閲覧できる。自分かどうかはDBの対象UUIDとセッションのUUIDで判断する。follower_id = 本人、フォロワー数は follow_id = 本人 の件数。向きごとの独立したサブクエリで数える。002 までを使う)。/profile/{ユーザーID}/edit は本人だけが使える。画面の表示時に加え、保存のたびにServer Actionでセッションと利用者を確認し、actorId === targetId のときだけ更新する(フォームの値や previousState は権限判断に使わない)。users_display_id_ci_unique の違反だけを競合として扱い、部分的な更新は起きない。revalidatePath でメイン・プロフィール・編集画面の表示を無効化し、表示用Cookie flash_profile で更新通知を出す(登録通知の flash とは別)。textarea の改行はブラウザがCRLFで送るため、自己紹介はサーバーでLFに揃えてから検証・保存する。/profile/{ユーザーID}/delete は本人だけが使える。ページ表示(GET)では削除せず、Server Actionで毎回セッションのUUIDを確認し、actorId === targetId かつ現在のパスワードが一致したときだけ削除する。DELETE FROM twitter.users WHERE id = ... の1文だけで行い、投稿・フォロー・リツイートは既存FKのON DELETE CASCADEで消える(論理削除・復元はなし)。revalidatePath で無効化し、Auth.jsの signOut({ redirect: false }) で認証Cookieを無効化してから /login へ移動する。通知は表示用Cookie flash_account(deleted / signout-failed / account-missing)で出す。BLOB_READ_WRITE_TOKEN / BLOB_STORE_ID(開発は .env.development.local)、テスト用は TEST_BLOB_READ_WRITE_TOKEN / TEST_BLOB_STORE_ID(.env)に書く。003-create-tweet-media.sql を pnpm db:migrate(開発)・pnpm db:migrate --test(テスト)で適用する。既存データの移行は不要。CRON_SECRET を登録する。vercel.json のCronが毎日 18:00 UTC(日本時間3:00)に回収を実行する(Hobbyプランの日次制約に合わせている)。This is the beginning of the README. Read the rest at the original. Read the full README ↗