Files
opengroupware/docs/ideas/initial-requirements.md
Ken Yasue 80e195b3dc chore: initialize repository with project docs and tooling
- Add persistent docs: PRD, functional design, architecture, repository structure, development guidelines, milestones

- Add brainstorming notes (docs/ideas/)

- Configure tooling: package.json, tsconfig, eslint, prettier, vitest

- Add opencode configuration (commands, skills, agents)

- Add .gitignore for node_modules, .env, data/, backups/, build outputs
2026-06-24 23:31:06 +02:00

36 KiB

シンプルグループウェア PRD

1. プロダクト概要

本プロダクトは、プロジェクト単位でチームの情報共有、タスク管理、ファイル共有、チャット、予定管理、ミーティング管理、Markdownメモ管理を行えるシンプルなグループウェアである。

すべての主要機能はプロジェクトに紐づき、プロジェクトごとに独立して利用できる。


2. 実装目的

今回実装する目的は以下である。

  • ユーザーを管理できる
  • プロジェクトを作成・管理できる
  • プロジェクトごとにメンバーを管理できる
  • プロジェクトごとに掲示板を使える
  • プロジェクトごとにSSEチャットを使える
  • プロジェクトごとにKanban形式のToDoを使える
  • プロジェクトごとにファイル共有を使える
  • ファイルをLightboxで閲覧できる
  • プロジェクトごとにMarkdownメモを作成・編集・閲覧できる
  • プロジェクトごとにカレンダーを使える
  • カレンダーでマイルストーン、デッドライン、ToDo、ミーティングを表示できる
  • プロジェクトごとにミーティングを管理できる
  • ミーティング作成時に参加メンバーの予定重複を確認できる
  • アプリ内通知を使える
  • アクティビティログを記録できる
  • SQLiteのDBスキーマをSQL Migrationで更新できる
  • 管理者がバックアップを作成できる

3. システム要件

3.1 技術スタック

  • フレームワーク: Next.js 15

  • 言語: TypeScript

  • データベース: SQLite

  • SQLiteライブラリ: better-sqlite3

  • ORM: 使用しない

  • DBアクセス: 独自SQLラッパー + Repositoryクラス

  • Migration: 独自SQL Migration

  • 認証: 独自ログイン方式

  • リアルタイム通信: SSE / Server-Sent Events

  • ファイル保存: ローカルファイルシステム

  • UI: Tailwind CSS

  • Markdown表示:

    • react-markdown
    • remark-gfm
    • rehype-sanitize
  • ファイル閲覧: Lightbox UI

  • カレンダーUI: FullCalendar系、または独自実装

  • 実行環境: Node.js runtime


3.2 Runtime方針

SQLiteを直接扱うため、Next.jsのEdge Runtimeは使用しない。

API Route、Server Actions、DBアクセス処理はすべてNode.js Runtimeで実行する。


3.3 Prismaは使用しない

本プロジェクトでは Prisma は使用しない。

DBアクセスは、独自SQLラッパーとRepositoryクラスで実装する。


4. 基本設計方針

4.1 DBアクセス構成

DBアクセスは以下の流れに統一する。

Route Handler / Server Action
  ↓
Repository Class
  ↓
SQL Wrapper
  ↓
SQLite

各Repositoryは直接SQLiteライブラリを触らず、必ず共通SQLラッパーを通してSQLを実行する。


4.2 ディレクトリ構成

app/
  api/
  login/
  dashboard/
  projects/
    [projectId]/

lib/
  db/
    sqlite.ts
    migrator.ts
    migrations/
      001_initial.sql

repositories/
  UserRepository.ts
  ProjectRepository.ts
  ProjectMemberRepository.ts
  BoardRepository.ts
  ChatRepository.ts
  TodoRepository.ts
  FileRepository.ts
  CalendarRepository.ts
  MeetingRepository.ts
  ProjectNoteRepository.ts
  NotificationRepository.ts
  ActivityLogRepository.ts

services/
  AuthService.ts
  ProjectService.ts
  ChatService.ts
  MeetingService.ts
  ScheduleService.ts
  FileStorageService.ts
  BackupService.ts

components/
  layout/
  project/
  board/
  chat/
  todo/
  files/
  calendar/
  meetings/
  notes/
  notifications/

5. SQL実行ラッパー

5.1 概要

SQLiteへのアクセスは、すべて共通のSQLラッパーを通して行う。

このラッパーは以下を担当する。

  • SELECT複数行取得
  • SELECT単一行取得
  • INSERT / UPDATE / DELETE実行
  • トランザクション
  • SQLite初期設定
  • 接続の共通管理
  • エラー処理

5.2 lib/db/sqlite.ts

import Database from "better-sqlite3";

export type SqlParams = Record<string, unknown> | unknown[];

export class SqliteDatabase {
  private db: Database.Database;

  constructor(dbPath: string) {
    this.db = new Database(dbPath);

    this.db.pragma("journal_mode = WAL");
    this.db.pragma("foreign_keys = ON");
  }

  query<T>(sql: string, params?: SqlParams): T[] {
    return this.db.prepare(sql).all(params ?? {}) as T[];
  }

  get<T>(sql: string, params?: SqlParams): T | null {
    const row = this.db.prepare(sql).get(params ?? {}) as T | undefined;
    return row ?? null;
  }

  execute(
    sql: string,
    params?: SqlParams
  ): {
    changes: number;
    lastInsertRowid: number | bigint;
  } {
    const result = this.db.prepare(sql).run(params ?? {});

    return {
      changes: result.changes,
      lastInsertRowid: result.lastInsertRowid,
    };
  }

  transaction<T>(callback: () => T): T {
    const tx = this.db.transaction(callback);
    return tx();
  }

  close(): void {
    this.db.close();
  }
}

let instance: SqliteDatabase | null = null;

export function getDb(): SqliteDatabase {
  if (!instance) {
    const dbPath = process.env.SQLITE_PATH ?? "./data/app.db";
    instance = new SqliteDatabase(dbPath);
  }

  return instance;
}

6. SQL Migration

6.1 概要

DBスキーマ更新は、SQLファイルベースの独自Migrationで実装する。

Migrationファイルは lib/db/migrations に配置する。

実行済みのMigrationは schema_migrations テーブルで管理する。


6.2 Migration要件

  • SQLファイルはファイル名順に実行する
  • 実行済みファイルは再実行しない
  • 実行済み履歴は schema_migrations テーブルに保存する
  • 1ファイルごとにトランザクションを張る
  • 失敗時はロールバックする
  • 管理者がMigration状態を確認できる

6.3 schema_migrations テーブル

CREATE TABLE IF NOT EXISTS schema_migrations (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  filename TEXT NOT NULL UNIQUE,
  applied_at TEXT NOT NULL
);

6.4 migrator.ts

import fs from "node:fs";
import path from "node:path";
import { SqliteDatabase } from "./sqlite";

export class Migrator {
  constructor(
    private readonly db: SqliteDatabase,
    private readonly migrationsDir: string
  ) {}

  migrate(): void {
    this.db.execute(`
      CREATE TABLE IF NOT EXISTS schema_migrations (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        filename TEXT NOT NULL UNIQUE,
        applied_at TEXT NOT NULL
      )
    `);

    const applied = this.db.query<{ filename: string }>(`
      SELECT filename
      FROM schema_migrations
    `);

    const appliedSet = new Set(applied.map((x) => x.filename));

    const files = fs
      .readdirSync(this.migrationsDir)
      .filter((file) => file.endsWith(".sql"))
      .sort();

    for (const file of files) {
      if (appliedSet.has(file)) continue;

      const fullPath = path.join(this.migrationsDir, file);
      const sql = fs.readFileSync(fullPath, "utf-8");

      this.db.transaction(() => {
        this.db.execute(sql);

        this.db.execute(
          `
          INSERT INTO schema_migrations (
            filename,
            applied_at
          )
          VALUES (
            @filename,
            @appliedAt
          )
          `,
          {
            filename: file,
            appliedAt: new Date().toISOString(),
          }
        );
      });
    }
  }
}

7. Repository設計

7.1 概要

テーブルごとにRepositoryクラスを作成する。

RepositoryはSQLを直接保持し、共通DBラッパーを通して実行する。


7.2 Repository一覧

  • UserRepository
  • ProjectRepository
  • ProjectMemberRepository
  • BoardRepository
  • ChatRepository
  • TodoRepository
  • FileRepository
  • CalendarRepository
  • MeetingRepository
  • ProjectNoteRepository
  • NotificationRepository
  • ActivityLogRepository

8. 基本コンセプト

すべての主要機能は「プロジェクト」に紐づく。

プロジェクトごとに以下が独立して存在する。

  • メンバー
  • 権限
  • 掲示板
  • チャット
  • ToDo / Kanban
  • ファイル
  • カレンダー
  • マイルストーン
  • デッドライン
  • ミーティング
  • Markdownメモ
  • 通知
  • アクティビティログ

ユーザーは複数のプロジェクトに参加できる。


9. 機能要件


9.1 ユーザー管理

概要

システムを利用するユーザーを管理する。

実装内容

  • ユーザー登録
  • ログイン
  • ログアウト
  • パスワードログイン
  • プロフィール編集
  • アイコン画像設定
  • 表示名設定
  • メールアドレス管理
  • アカウント有効 / 無効
  • ロール管理

ロール

  • System Admin
  • Project Admin
  • Member
  • Guest

9.2 プロジェクト管理

概要

プロジェクトを作成・管理する。

実装内容

  • プロジェクト作成
  • プロジェクト名編集
  • 説明文編集
  • ステータス管理
  • メンバー追加
  • メンバー削除
  • プロジェクト内ロール設定
  • プロジェクトアーカイブ
  • プロジェクト削除
  • プロジェクト別ダッシュボード

プロジェクトステータス

  • Active
  • On Hold
  • Completed
  • Archived

プロジェクトダッシュボード表示項目

  • 最新チャット
  • 最新掲示板投稿
  • 最新Markdownメモ
  • 未完了ToDo
  • 期限が近いToDo
  • 次回ミーティング
  • 直近のマイルストーン
  • 最近アップロードされたファイル
  • 最近のアクティビティ

9.3 掲示板

概要

プロジェクト単位で非リアルタイムの情報共有を行う。

実装内容

  • スレッド作成
  • スレッド編集
  • スレッド削除
  • Markdown本文投稿
  • コメント作成
  • コメント編集
  • コメント削除
  • 添付ファイル
  • 投稿のピン留め
  • 重要マーク
  • 既読管理
  • カテゴリ分類
  • 検索

カテゴリ

  • お知らせ
  • 仕様
  • 議事録
  • 質問
  • 決定事項
  • トラブル
  • メモ

9.4 チャット

概要

プロジェクト内でリアルタイムに短い会話を行う。

リアルタイム通信にはSSEを利用する。

実装内容

  • プロジェクト別チャット
  • メッセージ送信
  • SSEによるリアルタイム受信
  • メッセージ編集
  • メッセージ削除
  • 添付ファイル
  • メンション
  • リアクション
  • 既読 / 未読
  • チャット履歴検索

SSE要件

  • クライアントはプロジェクトごとのSSEエンドポイントに接続する
  • 新規メッセージ作成時にプロジェクト参加メンバーへイベント配信する
  • 接続切断時の自動再接続に対応する
  • SSEイベントはプロジェクト単位で配信する

SSEイベント

  • chat.message.created
  • chat.message.updated
  • chat.message.deleted
  • todo.updated
  • file.uploaded
  • meeting.created
  • note.updated
  • notification.created

9.5 ToDo / Kanban

概要

プロジェクトごとのタスクをKanban形式で管理する。

実装内容

  • Kanbanボード表示
  • カラム作成
  • カラム編集
  • カラム削除
  • カラム並び替え
  • タスク作成
  • タスク編集
  • タスク削除
  • タスクのドラッグ&ドロップ
  • 担当者設定
  • 期限設定
  • 優先度設定
  • ラベル設定
  • チェックリスト
  • コメント
  • 添付ファイル
  • 完了状態管理
  • カレンダーへの表示
  • マイルストーンとの紐づけ

標準カラム

  • Backlog
  • To Do
  • In Progress
  • Review
  • Done

9.6 ファイル共有

概要

プロジェクト内でファイルをアップロード、閲覧、共有する。

画像やPDFはLightboxで確認できるようにする。

実装内容

  • ファイルアップロード
  • ファイル一覧
  • フォルダ管理
  • ファイル名変更
  • ファイル削除
  • ダウンロード
  • プレビュー
  • Lightbox表示
  • 画像プレビュー
  • PDFプレビュー
  • ファイルコメント
  • ファイルとToDoの紐づけ
  • ファイルと掲示板投稿の紐づけ
  • ファイルとミーティングの紐づけ
  • ファイルとMarkdownメモの紐づけ

ファイル保存

アップロードされたファイルはローカルファイルシステムに保存する。


9.7 Markdownメモ

概要

プロジェクトごとにMarkdown形式のメモを作成・編集・閲覧できる。

実装内容

  • Markdownメモ作成
  • Markdownメモ編集
  • Markdownメモ削除
  • Markdownプレビュー
  • タイトル設定
  • タグ設定
  • ピン留め
  • 検索
  • 更新日時表示
  • 作成者表示
  • 最終更新者表示
  • ファイル添付
  • 関連ToDo設定
  • 関連ミーティング設定

画面構成

プロジェクト内に「メモ」メニューを追加する。

プロジェクト
  - 概要
  - 掲示板
  - チャット
  - ToDo
  - ファイル
  - メモ
  - カレンダー
  - ミーティング
  - メンバー
  - 設定

Markdown対応記法

  • 見出し
  • 箇条書き
  • 番号リスト
  • チェックリスト
  • コードブロック
  • テーブル
  • リンク
  • 画像
  • 引用

Markdownセキュリティ

  • HTMLの直接入力は無効にする
  • Markdown表示時にサニタイズする
  • 危険なURLスキームを除外する

9.8 カレンダー

概要

プロジェクト内の予定、マイルストーン、ToDo期限、ミーティングをカレンダー上で確認する。

実装内容

  • 月表示
  • 週表示
  • 日表示
  • リスト表示
  • マイルストーン表示
  • ToDo期限表示
  • デッドライン表示
  • ミーティング表示
  • イベント作成
  • イベント編集
  • イベント削除
  • メンバー別フィルター
  • 種別フィルター

表示対象

  • マイルストーン
  • デッドライン
  • ToDo開始日
  • ToDo期限
  • ミーティング
  • 任意イベント

カレンダーイベント種別

  • Meeting
  • Deadline
  • Milestone
  • Todo
  • Reminder
  • Custom

9.9 マイルストーン管理

概要

プロジェクトの重要な節目を管理する。

実装内容

  • マイルストーン作成
  • マイルストーン編集
  • マイルストーン削除
  • 期限設定
  • 説明文
  • 関連ToDo
  • 進捗率表示
  • 完了状態管理
  • カレンダー表示

進捗率

関連ToDoの完了率から自動計算する。


9.10 ミーティング管理

概要

プロジェクトメンバーとのミーティングを設定し、参加者の予定重複を確認できるようにする。

実装内容

  • ミーティング作成
  • ミーティング編集
  • ミーティング削除
  • タイトル設定
  • 説明設定
  • 開始日時設定
  • 終了日時設定
  • 参加メンバー設定
  • 場所設定
  • ミーティングURL設定
  • アジェンダ作成
  • 議事録作成
  • 関連ToDo設定
  • 関連ファイル設定
  • 関連掲示板投稿設定
  • 関連Markdownメモ設定
  • カレンダー表示
  • 参加者の予定重複チェック

スケジュール重複確認

ミーティング作成時に、選択されたメンバーの予定を確認し、同じ時間帯に以下がある場合は警告する。

  • 他のミーティング
  • カレンダーイベント
  • 期限の近い重要タスク

9.11 通知

概要

ユーザーが重要な更新を見逃さないようにアプリ内通知を表示する。

実装内容

  • アプリ内通知
  • 未読通知一覧
  • 通知既読化
  • メンション通知
  • ToDo担当者通知
  • 期限前通知
  • ミーティング通知
  • 掲示板コメント通知
  • ファイル共有通知
  • Markdownメモ更新通知

通知対象イベント

  • 自分がメンションされた
  • 自分にToDoが割り当てられた
  • ToDoの期限が近い
  • ミーティングに招待された
  • 掲示板にコメントが付いた
  • プロジェクトに追加された
  • ファイルが共有された
  • Markdownメモが更新された

9.12 検索

概要

プロジェクト内の情報を横断検索できるようにする。

実装内容

  • 掲示板検索
  • チャット検索
  • ToDo検索
  • ファイル名検索
  • カレンダーイベント検索
  • ミーティング検索
  • 議事録検索
  • マイルストーン検索
  • Markdownメモ検索

検索条件

  • キーワード
  • 投稿者
  • 担当者
  • 日付
  • 種別
  • プロジェクト
  • タグ

9.13 アクティビティログ

概要

プロジェクト内の変更履歴を時系列で確認できるようにする。

実装内容

以下の操作をアクティビティログに記録する。

  • ToDo作成
  • ToDo更新
  • ToDo完了
  • ファイルアップロード
  • 掲示板投稿
  • コメント追加
  • Markdownメモ作成
  • Markdownメモ更新
  • ミーティング作成
  • メンバー追加
  • マイルストーン更新

9.14 ダッシュボード

概要

ログイン後、ユーザーが自分に関係する情報を確認できる画面。

個人ダッシュボード

  • 自分の参加プロジェクト
  • 自分の未完了ToDo
  • 今日の予定
  • 近日中のミーティング
  • 未読通知
  • 期限切れタスク
  • 最近のアクティビティ

プロジェクトダッシュボード

  • プロジェクト概要
  • 進行中ToDo
  • 期限が近いToDo
  • 最新チャット
  • 最新掲示板
  • 最新Markdownメモ
  • 最近のファイル
  • 次回ミーティング
  • マイルストーン進捗

9.15 バックアップ

概要

管理者がSQLite DBファイルとアップロードファイルをバックアップできるようにする。

実装内容

  • 管理者用バックアップ画面
  • SQLite DBファイルのバックアップ作成
  • uploadsディレクトリのバックアップ作成
  • DBとuploadsをZIP化
  • バックアップファイル一覧
  • バックアップファイルのダウンロード

10. データモデル


10.1 users

CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE,
  password_hash TEXT,
  avatar_url TEXT,
  role TEXT NOT NULL DEFAULT 'member',
  status TEXT NOT NULL DEFAULT 'active',
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

10.2 projects

CREATE TABLE projects (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  description TEXT,
  status TEXT NOT NULL DEFAULT 'active',
  owner_id INTEGER NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (owner_id) REFERENCES users(id)
);

10.3 project_members

CREATE TABLE project_members (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  user_id INTEGER NOT NULL,
  role TEXT NOT NULL DEFAULT 'member',
  joined_at TEXT NOT NULL,
  UNIQUE(project_id, user_id),
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

10.4 board_threads

CREATE TABLE board_threads (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  body_md TEXT NOT NULL,
  author_id INTEGER NOT NULL,
  category TEXT,
  is_pinned INTEGER NOT NULL DEFAULT 0,
  is_important INTEGER NOT NULL DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (author_id) REFERENCES users(id)
);

10.5 board_comments

CREATE TABLE board_comments (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  thread_id INTEGER NOT NULL,
  author_id INTEGER NOT NULL,
  body_md TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (thread_id) REFERENCES board_threads(id) ON DELETE CASCADE,
  FOREIGN KEY (author_id) REFERENCES users(id)
);

10.6 chat_messages

CREATE TABLE chat_messages (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  author_id INTEGER NOT NULL,
  body TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (author_id) REFERENCES users(id)
);

10.7 todo_columns

CREATE TABLE todo_columns (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  name TEXT NOT NULL,
  order_index INTEGER NOT NULL DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);

10.8 todo_items

CREATE TABLE todo_items (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  column_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  assignee_id INTEGER,
  creator_id INTEGER NOT NULL,
  priority TEXT NOT NULL DEFAULT 'normal',
  start_date TEXT,
  due_date TEXT,
  completed_at TEXT,
  order_index INTEGER NOT NULL DEFAULT 0,
  milestone_id INTEGER,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (column_id) REFERENCES todo_columns(id) ON DELETE CASCADE,
  FOREIGN KEY (assignee_id) REFERENCES users(id),
  FOREIGN KEY (creator_id) REFERENCES users(id)
);

10.9 file_assets

CREATE TABLE file_assets (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  uploader_id INTEGER NOT NULL,
  filename TEXT NOT NULL,
  original_name TEXT NOT NULL,
  mime_type TEXT NOT NULL,
  size INTEGER NOT NULL,
  path TEXT NOT NULL,
  created_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (uploader_id) REFERENCES users(id)
);

10.10 project_notes

CREATE TABLE project_notes (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  body_md TEXT NOT NULL,
  tags TEXT,
  is_pinned INTEGER NOT NULL DEFAULT 0,
  created_by_id INTEGER NOT NULL,
  updated_by_id INTEGER NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (created_by_id) REFERENCES users(id),
  FOREIGN KEY (updated_by_id) REFERENCES users(id)
);

CREATE INDEX idx_project_notes_project_id
ON project_notes(project_id);

CREATE INDEX idx_project_notes_updated_at
ON project_notes(updated_at);

10.11 milestones

CREATE TABLE milestones (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  due_date TEXT,
  status TEXT NOT NULL DEFAULT 'open',
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);

10.12 calendar_events

CREATE TABLE calendar_events (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  type TEXT NOT NULL,
  start_at TEXT NOT NULL,
  end_at TEXT,
  created_by_id INTEGER NOT NULL,
  related_todo_id INTEGER,
  related_milestone_id INTEGER,
  related_meeting_id INTEGER,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (created_by_id) REFERENCES users(id)
);

10.13 meetings

CREATE TABLE meetings (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  location TEXT,
  meeting_url TEXT,
  start_at TEXT NOT NULL,
  end_at TEXT NOT NULL,
  agenda_md TEXT,
  minutes_md TEXT,
  created_by_id INTEGER NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  deleted_at TEXT,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (created_by_id) REFERENCES users(id)
);

10.14 meeting_members

CREATE TABLE meeting_members (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  meeting_id INTEGER NOT NULL,
  user_id INTEGER NOT NULL,
  status TEXT NOT NULL DEFAULT 'invited',
  UNIQUE(meeting_id, user_id),
  FOREIGN KEY (meeting_id) REFERENCES meetings(id) ON DELETE CASCADE,
  FOREIGN KEY (user_id) REFERENCES users(id)
);

10.15 notifications

CREATE TABLE notifications (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id INTEGER NOT NULL,
  project_id INTEGER,
  type TEXT NOT NULL,
  title TEXT NOT NULL,
  body TEXT,
  read_at TEXT,
  created_at TEXT NOT NULL,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);

10.16 activity_logs

CREATE TABLE activity_logs (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL,
  actor_id INTEGER NOT NULL,
  action TEXT NOT NULL,
  target_type TEXT NOT NULL,
  target_id INTEGER,
  metadata_json TEXT,
  created_at TEXT NOT NULL,
  FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
  FOREIGN KEY (actor_id) REFERENCES users(id)
);

11. 画面構成

11.1 共通画面

  • ログイン画面
  • ダッシュボード
  • 通知一覧
  • ユーザープロフィール
  • 管理者設定
  • バックアップ管理

11.2 プロジェクト内画面

  • プロジェクト概要
  • 掲示板
  • チャット
  • ToDo / Kanban
  • ファイル
  • Markdownメモ
  • カレンダー
  • マイルストーン
  • ミーティング
  • メンバー
  • アクティビティログ
  • 設定

12. 非機能要件

12.1 パフォーマンス

  • 1プロジェクトあたり数十人規模を想定する
  • チャットSSEは小規模同時接続を前提とする
  • ファイル一覧、チャット履歴、掲示板、Markdownメモはページネーションを行う
  • 一覧取得では必要な件数だけ取得する

12.2 セキュリティ

  • 認証必須
  • プロジェクト参加者以外はプロジェクト情報にアクセス不可
  • ファイルアクセスにも権限チェックを行う
  • SQLはパラメータバインドで実行する
  • Markdown表示時はHTMLを無効化しサニタイズする
  • アップロードファイルのMIMEチェックを行う
  • 管理者操作をアクティビティログに記録する

12.3 バックアップ

  • SQLite DBファイルをバックアップできる
  • uploadsディレクトリをバックアップできる
  • DBとuploadsをZIP化できる
  • バックアップファイルをダウンロードできる

12.4 運用

  • .env で設定管理できる
  • SQLite DBファイルを永続化する
  • uploadsディレクトリを永続化する
  • 管理者がDB Migration状態を確認できる
  • 管理者がバックアップを作成できる

13. 開発順序

Phase 1: 基盤

  • Next.js 15セットアップ
  • Tailwind CSSセットアップ
  • SQLite接続
  • SQLラッパー実装
  • Migration実装
  • Repository基盤作成
  • 認証
  • ユーザー管理
  • プロジェクト管理
  • プロジェクトメンバー管理

Phase 2: プロジェクト内基本機能

  • プロジェクトダッシュボード
  • 掲示板
  • Markdownメモ
  • アクティビティログ
  • 通知

Phase 3: リアルタイム・タスク管理

  • SSE基盤
  • チャット
  • ToDo / Kanban
  • メンション
  • 既読 / 未読

Phase 4: ファイル・カレンダー

  • ファイル共有
  • Lightbox
  • カレンダー
  • マイルストーン
  • デッドライン表示

Phase 5: ミーティング・バックアップ

  • ミーティング作成
  • メンバー設定
  • スケジュール重複チェック
  • 議事録
  • ToDo連携
  • Markdownメモ連携
  • バックアップ管理

14. 成功条件

  • ユーザーがログインできる
  • ユーザーを管理できる
  • プロジェクトを作成できる
  • プロジェクトにメンバーを追加できる
  • プロジェクトごとに掲示板を使える
  • プロジェクトごとにチャットを使える
  • チャットがSSEでリアルタイム更新される
  • プロジェクトごとにKanban ToDoを使える
  • プロジェクトごとにファイルをアップロードできる
  • ファイルをLightboxで閲覧できる
  • プロジェクトごとにMarkdownメモを作成・編集・閲覧できる
  • カレンダーにToDo、マイルストーン、デッドライン、ミーティングが表示される
  • ミーティングを作成できる
  • ミーティング参加者の予定重複が分かる
  • アプリ内通知が表示される
  • アクティビティログが記録される
  • SQL Migrationが実行できる
  • 管理者がDBとuploadsのバックアップを作成できる

15. まとめ

本プロダクトは、Next.js 15、TypeScript、SQLite、better-sqlite3で構築するシンプルなプロジェクト型グループウェアである。

Prismaは使用せず、独自SQLラッパーとRepositoryクラスでDBアクセスを実装する。

DB更新はSQLファイルベースの独自Migrationで管理する。

今回実装する機能は、ユーザー管理、プロジェクト管理、掲示板、SSEチャット、Kanban ToDo、ファイル共有、Lightbox、Markdownメモ、カレンダー、マイルストーン、ミーティング管理、通知、アクティビティログ、バックアップである。

すべての主要機能はプロジェクトに紐づき、プロジェクトごとに独立して利用できる。

3.4 テスト要件

本プロジェクトでは、Unit Test と E2E Test を実装する。

Unit Test

Unit Test は、主に以下を対象とする。

  • SQLラッパー
  • Migration
  • Repositoryクラス
  • Serviceクラス
  • 権限チェック
  • バリデーション
  • スケジュール重複判定
  • 通知作成ロジック
  • アクティビティログ作成ロジック

E2E Test

E2E Test は Playwright を使用して実装する。

E2E Test は、実際のブラウザ操作を通して、主要なユーザーフローが正しく動作することを確認する。

テストライブラリ

  • Unit Test: Vitest
  • E2E Test: Playwright

9.16 テスト

概要

今回実装する全機能について、Unit Test と PlaywrightによるE2E Testを作成する。

Unit Test実装内容

Unit Testでは、UIではなくロジック単位の動作を確認する。

対象:

  • SQLラッパー
  • Migration実行
  • UserRepository
  • ProjectRepository
  • ProjectMemberRepository
  • BoardRepository
  • ChatRepository
  • TodoRepository
  • FileRepository
  • CalendarRepository
  • MeetingRepository
  • ProjectNoteRepository
  • NotificationRepository
  • ActivityLogRepository
  • AuthService
  • ProjectService
  • ChatService
  • MeetingService
  • ScheduleService
  • FileStorageService
  • BackupService

確認内容:

  • 正常にデータを作成できる
  • 正常にデータを取得できる
  • 正常にデータを更新できる
  • 正常にデータを削除できる
  • 論理削除されたデータが通常取得に含まれない
  • プロジェクト単位でデータが分離される
  • 権限がないユーザーは操作できない
  • 必須項目が不足している場合はエラーになる
  • Migrationがファイル名順に実行される
  • 実行済みMigrationが再実行されない
  • 予定が重複している場合に検出できる
  • 通知が正しいユーザーに作成される
  • アクティビティログが正しく記録される

E2E Test実装内容

E2E Testでは、Playwrightを使用して実際の画面操作を検証する。

対象フロー:

認証

  • ユーザーがログインできる
  • ユーザーがログアウトできる
  • ログインしていないユーザーは保護された画面にアクセスできない

プロジェクト管理

  • プロジェクトを作成できる
  • プロジェクト名を編集できる
  • プロジェクトにメンバーを追加できる
  • プロジェクトからメンバーを削除できる
  • プロジェクトをアーカイブできる

掲示板

  • 掲示板スレッドを作成できる
  • 掲示板スレッドを編集できる
  • 掲示板スレッドにコメントできる
  • 掲示板スレッドを検索できる

チャット

  • チャットメッセージを送信できる
  • 別ブラウザ、または別コンテキストでSSEによりメッセージがリアルタイム表示される
  • チャットメッセージを編集できる
  • チャットメッセージを削除できる

ToDo / Kanban

  • ToDoカラムを作成できる
  • ToDoタスクを作成できる
  • ToDoタスクを編集できる
  • ToDoタスクを別カラムへ移動できる
  • ToDoタスクに担当者と期限を設定できる
  • 完了したToDoがDoneカラムに表示される

ファイル共有

  • ファイルをアップロードできる
  • ファイル一覧に表示される
  • 画像ファイルをLightboxで閲覧できる
  • PDFファイルをプレビューできる
  • ファイルを削除できる

Markdownメモ

  • Markdownメモを作成できる
  • Markdown本文を編集できる
  • Markdownプレビューが表示される
  • Markdownメモをピン留めできる
  • Markdownメモを検索できる
  • Markdownメモを削除できる

カレンダー

  • カレンダーにToDo期限が表示される
  • カレンダーにマイルストーンが表示される
  • カレンダーにミーティングが表示される
  • カレンダーイベントを作成できる
  • カレンダーイベントを編集できる

ミーティング

  • ミーティングを作成できる
  • ミーティングに参加メンバーを設定できる
  • 参加メンバーの予定重複が画面上で警告される
  • アジェンダを入力できる
  • 議事録を入力できる
  • ミーティングをToDoやMarkdownメモに関連付けできる

通知

  • ToDo担当者に通知が表示される
  • メンションされたユーザーに通知が表示される
  • ミーティング参加者に通知が表示される
  • 通知を既読にできる

アクティビティログ

  • ToDo作成がログに記録される
  • ファイルアップロードがログに記録される
  • Markdownメモ更新がログに記録される
  • ミーティング作成がログに記録される

バックアップ

  • 管理者がバックアップを作成できる
  • バックアップ一覧に作成済みバックアップが表示される
  • バックアップファイルをダウンロードできる

14. 成功条件 / 受け入れ要件

  • ユーザーがログインできる
  • ユーザーを管理できる
  • プロジェクトを作成できる
  • プロジェクトにメンバーを追加できる
  • プロジェクトごとに掲示板を使える
  • プロジェクトごとにチャットを使える
  • チャットがSSEでリアルタイム更新される
  • プロジェクトごとにKanban ToDoを使える
  • プロジェクトごとにファイルをアップロードできる
  • ファイルをLightboxで閲覧できる
  • プロジェクトごとにMarkdownメモを作成・編集・閲覧できる
  • カレンダーにToDo、マイルストーン、デッドライン、ミーティングが表示される
  • ミーティングを作成できる
  • ミーティング参加者の予定重複が分かる
  • アプリ内通知が表示される
  • アクティビティログが記録される
  • SQL Migrationが実行できる
  • 管理者がDBとuploadsのバックアップを作成できる
  • Unit Testが実装されている
  • Repository、Service、Migration、SQLラッパーのUnit Testが実行できる
  • PlaywrightによるE2E Testが実装されている
  • 主要ユーザーフローのE2E Testが実行できる
  • npm test でUnit Testが実行できる
  • npm run test:e2e でPlaywright E2E Testが実行できる
  • Unit TestとE2E Testがすべて成功する