タスク管理アプリ

https://github.com/4wawq/webpro-task-app

GitHub

JavaScript

Node.js

MySQL

HTML

タスク管理を行えるサービス

小川碧海

推しアイデア

タスクの重要度を設定できるようにしたこと。

作った背景

3年になり課題に追われる毎日。課題の提出を忘れることも何度かあり、タスク管理アプリを作成したくなった。

推し技術

期限が近いものから順に表示させ、期限が1日を切る重要度が高く変化する点。

プロジェクト詳細

タスク管理 Web アプリ

慶應義塾大学「実践のためのWebプログラミング」(2026年春学期) 最終課題として制作した, タスク管理 Web アプリである。フロントエンド・バックエンド・データベースの三層構成をとり, 締切の近いタスクの重要度をサーバ側で自動的に引き上げて色分け表示する。

主な機能

  • タスクの一覧表示, 追加, 完了, 削除 (CRUD)
  • 重要度 (低 / 中 / 高) 別の色分け表示
  • 締切接近による重要度の自動引き上げ。 期限が近いタスクは, ユーザ設定の重要度に関わらず一覧表示時に格上げされる
  • 期限切れのペナルティ点。 未完了のまま期限を過ぎたタスクに超過日数に応じたペナルティ点を与え, 件数と合計を表示する
  • タスクの分類に使うカテゴリの一覧表示と追加
  • メールアドレスとパスワードによる新規登録とログイン。パスワードは scrypt でハッシュ化して保存し, 平文は持たない
  • Cookie / セッションによる持ち主の識別。ログインしたユーザ自身のタスクだけが見え, 他人のタスクは一覧にも操作対象にも現れない

アーキテクチャ

設計.txt (第10回 設計演習) で決めた三層構成に対応する。

[ フロントエンド ] <--JSON--> [ バックエンド ] <--Prisma--> [ PostgreSQL ] HTML / CSS / TypeScript Node.js + Express Render 上
  • フロントエンドは静的ファイルとして Express から配信し, fetch で JSON API を叩く
  • バックエンドはルーティングを routes/, 処理を controllers/, DB アクセスを models/ に分けた MVC 寄りの構成
  • データベースへのアクセスは Prisma 経由

技術スタック

技術
フロントエンドHTML, CSS, TypeScript (バンドラ無し, tscapp.js を生成)
バックエンドNode.js, Express 5, express-session
ORMPrisma 7 (driver adapter 方式, @prisma/adapter-pg)
データベースPostgreSQL
デプロイRender (Blueprint / render.yaml)

ディレクトリ構成

task-app/ ├── backend/ │ ├── server.ts # Express の起動, ミドルウェア設定, 静的配信 │ ├── routes/ # ルーティング (auth.ts, tasks.ts, categories.ts) │ ├── controllers/ # リクエスト処理 (authController.ts, tasksController.ts, categoriesController.ts) │ ├── models/prisma.ts # Prisma クライアントの初期化 │ ├── middleware/requireAuth.ts # 未ログインを 401 で弾く │ ├── auth/password.ts # パスワードの scrypt ハッシュ化と照合 │ ├── importance.ts # 締切接近による重要度の算出 │ └── penalty.ts # 期限切れタスクのペナルティ点の算出 ├── frontend/ │ ├── index.html │ ├── style.css │ └── app.ts # 画面のロジック (ビルドすると app.js) ├── prisma/ │ ├── schema.prisma # DB スキーマ定義 │ ├── migrations/ # マイグレーション │ └── seed.ts # サンプルデータ投入 ├── render.yaml # Render の Blueprint (Web + PostgreSQL) └── package.json

データベーススキーマ

tasks から userscategories へそれぞれ 1 対多の外部キーを張る。

  • usersid, name, email, password_hash (email は一意。password_hash は scrypt の "salt:derivedKey" hex 形式で, 平文は保存しない)
  • categoriesid, name, color
  • tasksid, title, deadline, importance_level, is_completed, user_id, category_id

API

タスク系とカテゴリ系のエンドポイントはすべてログイン必須で, 未ログインだと 401 を返す。

メソッドパス説明
POST/registername, email, password を受け取り, ユーザを新規作成してログイン状態にする
POST/loginemail と password を受け取り, 照合が通ればセッションに記録する
POST/logoutセッションを破棄する
GET/meログイン中のユーザを返す
GET/tasksログイン中ユーザのタスク一覧を返す (重要度の自動引き上げとペナルティ点を付けて返す)
POST/tasksタスクを新規作成する
PATCH/tasks/:idタスクを部分更新する
DELETE/tasks/:idタスクを削除する
GET/categoriesカテゴリ一覧を返す
POST/categoriesカテゴリを新規作成する (color は #rrggbb 形式)

重要度の自動引き上げ (設計の肝)

このアプリの中心的な仕組みである。ユーザが設定した重要度 (importance_level) はそのまま DB に保存するが, 締切が近いタスクは GET /tasks の応答を組み立てるときに, より高い重要度へ引き上げてから返す。引き上げた値は DB に書き戻さない。

  • 期限まで 24時間以内 (期限切れを含む) → 高 (3)
  • 期限まで 72時間以内中 (2)
  • それ以外 → ユーザ設定値のまま

ユーザ設定値と締切由来の値のうち高い方を採用するため, 引き上げは行っても引き下げはしない。フロントエンドはこの実効重要度を見て色を変えるだけであり, 判定ロジックはバックエンドに一本化されている。これは importance_level を Single Source of Truth とし, 「期限まであと何時間か」から導ける値を DB に二重に持たないための設計である (第09回 DBとORM)。

期限切れのペナルティ点

重要度の自動引き上げと同じ方針で, 未完了のまま期限を過ぎたタスクにペナルティ点を与える。この値も DB には持たず, GET /tasks の応答時に deadline と現在時刻から算出して返す。

  • 超過日数 (切り上げ, 最低 1 日) × 10 点を与える
  • 完了済み, および期限内のタスクは 0 点
  • 応答には各タスクの isOverduepenaltyPoints を含め, フロントエンドは期限切れの件数とペナルティ合計を表示する

「期限からどれだけ過ぎたか」は deadline から導けるため, ペナルティ点を DB に二重に持たせない (第09回 DBとORM)。点数の配分は暫定値である。

ローカルでの起動

前提として, ローカルに PostgreSQL が動いており, .envDATABASE_URLSESSION_SECRET が設定されていること。.env.gitignore 済みで, リポジトリには含めない。

npm install # 依存のインストール (postinstall で prisma generate も走る) npx prisma migrate deploy # マイグレーションの適用 npx tsx prisma/seed.ts # サンプルデータの投入 npm run build:frontend # frontend/app.ts を app.js にビルド npm run dev # バックエンドを起動 (tsx watch)

起動後, ブラウザで http://localhost:3000 を開く。backend/ を編集すると自動再起動する。フロントエンド (frontend/app.ts) を変更したときは npm run build:frontendapp.js を作り直す。

デプロイ (Render)

render.yaml を Blueprint として使い, Web サービスと PostgreSQL をまとめて作成する。

  • ビルド: npm ci --include=dev && npm run build && npx prisma migrate deploy
  • 起動: npm start (node dist/server.js)
  • DATABASE_URL は Render の DB から自動注入し, SESSION_SECRET は自動生成する。秘密情報は .env をコミットせず, すべて環境変数で渡す
  • 本番は TLS をプロキシで終端するため, app.set("trust proxy", 1) を有効にし, secure Cookie が送出されるようにしている

本番 DB は初回デプロイ後に, ローカルから外部接続 URL 経由で一度だけ seed.ts を実行して投入する。

ログイン用アカウント (seed 済み)

新規登録から作成することもできるが, 動作確認には seed で投入済みの下記アカウントが使える。いずれもパスワードは password123 である。

  • aoiogawa0814@example.com (タスク 3 件)
  • taro@example.com (別ユーザ。認証分離の確認用)

小川碧海

@0f7d07604d08a2db