Django、React、Next.js、PostgreSQL、docker compose を利用したタスク管理サイトの実装リポジトリです。
環境変数の例は .env.example を参照してください。local の初期値は docker-compose.yml にも定義済みです。
docker compose up --build起動後、以下を確認できます。
- Frontend: http://localhost:3000/login
- Backend health check: http://localhost:8000/api/health/
- PostgreSQL:
localhost:5432
health check は以下を返します。
{
"status": "ok"
}| service | port | description |
|---|---|---|
frontend |
3000 |
Next.js |
backend |
8000 |
Django REST Framework |
db |
5432 |
PostgreSQL 16 |
Backend は Django REST Framework を利用し、API は JSON response を返します。認証方式は Cookie ベースの session 認証を標準とし、状態変更 API では CSRF token を必須にします。
Backend は以下の環境変数で設定します。
DJANGO_SECRET_KEY=local-secret
DJANGO_DEBUG=true
DATABASE_URL=postgres://app:app@db:5432/app
ALLOWED_HOSTS=localhost,127.0.0.1,backend
CSRF_TRUSTED_ORIGINS=http://localhost:3000
CORS_ALLOWED_ORIGINS=http://localhost:3000
SESSION_COOKIE_SECURE=false
CSRF_COOKIE_SECURE=false
SESSION_COOKIE_AGE=28800
LOGIN_RATE_LIMIT_ATTEMPTS=5
LOGIN_RATE_LIMIT_WINDOW_SECONDS=300API error は以下の形式に揃えます。
{
"code": "VALIDATION_ERROR",
"message": "入力内容を確認してください",
"details": {
"email": ["メールアドレスを正しく入力してください"]
}
}主な error code は以下です。
| HTTP status | code | 用途 |
|---|---|---|
400 |
VALIDATION_ERROR |
入力値不正 |
401 |
UNAUTHENTICATED |
未ログイン |
403 |
FORBIDDEN |
権限不足 |
403 |
CSRF_FAILED |
CSRF 検証失敗 |
404 |
NOT_FOUND |
対象リソースなし |
405 |
METHOD_NOT_ALLOWED |
許可されていない HTTP method |
500 |
INTERNAL_SERVER_ERROR |
予期しない server error |
500 response には stack trace、SQL、内部 path を含めません。
- session cookie は
HttpOnly/SameSite=Laxです。 - session 有効期限の初期値は 8 時間です。
- local CORS は
http://localhost:3000のみ許可します。 - password、session id、CSRF token は log に出力しない方針です。
Backend API access log は method、path、status、duration_ms を stdout に出力します。request body や Cookie header は access log に出力しません。
docker compose run --rm backend python manage.py test認証 API は Cookie ベースの session 認証を利用します。状態変更 API のため、POST /api/auth/login/ と POST /api/auth/logout/ では CSRF token が必須です。
GET /api/auth/csrf/CSRF cookie を発行し、以下を返します。
{
"csrfToken": "..."
}POST /api/auth/login/
Content-Type: application/json
X-CSRFToken: {csrfToken}{
"email": "user@example.com",
"password": "password123"
}成功時は session cookie を発行し、以下を返します。
{
"user": {
"id": "usr_xxx",
"email": "user@example.com",
"displayName": "山田 太郎"
}
}認証失敗時は 401 INVALID_CREDENTIALS を返します。ログイン失敗は初期値として 5 回 / 5 分 で rate limit し、超過時は 429 RATE_LIMITED を返します。
GET /api/auth/me/ログイン中のユーザー情報を返します。未ログイン時は 401 UNAUTHENTICATED です。
POST /api/auth/logout/
X-CSRFToken: {csrfToken}成功時は session を破棄し、204 No Content を返します。
MVP の永続化は Django custom user model と task model で構成します。
- API 上の ID は string として扱います。
users.idはusr_prefix の string primary key です。tasks.idはtsk_prefix の string primary key です。- Frontend では ID を数値変換しません。
| table | description |
|---|---|
users |
ログインユーザー |
django_session |
Django 標準 session |
tasks |
タスク本体 |
tasks は MVP ではユーザー個人所有モデルです。削除方式は deleted_at を使う論理削除を前提にし、一覧・詳細・summary API では deleted_at IS NULL のタスクのみ扱います。
docker compose run --rm backend python manage.py migratedocker compose run --rm backend python manage.py createsuperuser対話式で email、display_name、password を入力してください。
Frontend の API 呼び出しは frontend/src/lib/api/ 以下の共通クライアントを使います。
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000import { login, logout, getCurrentUser } from "@/lib/api/auth";
import { getHomeSummary } from "@/lib/api/home";
import { listTasks, createTask, updateTask, deleteTask } from "@/lib/api/tasks";
import { isApiError } from "@/lib/api/errors";
// 認証
const { user } = await login("user@example.com", "password");
await logout();
const { user: me } = await getCurrentUser();
// ホーム summary
const summary = await getHomeSummary();
// summary.taskTotal / summary.taskOpen / summary.taskOverdue
// タスク
const { results, count } = await listTasks({ status: "todo" });
const task = await createTask({ title: "新しいタスク", dueDate: "2026-06-01" });
await updateTask(task.id, { status: "done" });
await deleteTask(task.id);
// エラーハンドリング
try {
await login("user@example.com", "wrong");
} catch (e) {
if (isApiError(e)) {
if (e.isUnauthenticated()) { /* 401 */ }
if (e.isValidationError()) { /* 400 + e.details */ }
if (e.isCsrfFailed()) { /* 403 CSRF_FAILED */ }
}
}POST / PUT / PATCH / DELETE では X-CSRFToken を自動付与します。
token は csrftoken cookie から取得し、未設定の場合は GET /api/auth/csrf/ にフォールバックします。
cd frontend && npm test- local DB は named volume
postgres_dataに保存されます。 - volume を削除すると local DB のデータは消えます。
- production 用の secrets 管理、TLS、監視、CI/CD は MVP 基盤 issue の対象外です。