Skip to content

Design Doc: Moonshot (PoC)

  • Status: PoC In Progress
  • Last Updated: 2026-04-21
  • Author: Lead Engineer
  • Phase: PoC (Phase 2 移行判断は本PoC完了後)

ターゲットユーザー: フロー状態を重んじるソフトウェアエンジニア(個人〜小規模チーム)。

課題: Jira, Asana 等の既存OKRツールは画面遷移とモーダルが多く、OKR更新自体が 「重いタスク」化している。結果としてOKRが形骸化する。

仮説: テキストエディタのような軽快さ(モードレス・インライン編集)と 深宇宙×ダークモードの世界観で、OKR更新を「毎日のワクワクするルーティン」に変えられるのではないか。 このPoCはこの仮説の技術的成立性を検証する。

  • モードレスな体験: インライン編集 + 楽観的UIによる遅延ゼロ感
  • 型安全性の貫通: DBスキーマ〜UIコンポーネントまでTypeScript型を完全同期
  • View Transitions API によるネイティブライクな状態遷移
  • チーム間コラボ(メンション、コメント)
  • RBAC / カスタムワークフロー / SAML SSO
  • モバイルネイティブアプリ
  • Slack / Teams 連携
  • ガントチャート / タイムライン表示

3. PoC で検証する仮説と成功基準

Section titled “3. PoC で検証する仮説と成功基準”

検証対象は次の 3 仮説。各仮説について MUST(成功条件)/ SHOULD(あれば良い)/ STOP(中止条件) の 3 段階で判定する。

H1 (UX): モードレス + 楽観的UIで OKR 更新が苦じゃなくなる

Section titled “H1 (UX): モードレス + 楽観的UIで OKR 更新が苦じゃなくなる”
区分条件
MUSTDogfooding 1 週間(7 営業日)連続使用、daily で OKR 更新
MUST「既存 OKR ツールより更新が苦じゃない」と主観評価で yes
SHOULD1 日あたり 3 操作以上(Objective / KR / Task の作成 or 編集)
STOP「結局 Notion / スプレッドシートに戻りたい」と感じたら H1 否定

H2 (技術): Hono + TanStack Query で 3 階層楽観的更新が破綻なく実装可

Section titled “H2 (技術): Hono + TanStack Query で 3 階層楽観的更新が破綻なく実装可”
区分条件
MUST「保存されたように見えて未保存」が Dogfooding 期間中 0 件
MUST競合編集(同一ブラウザ複数タブ)で 409 が UI に通知される
MUST全 mutation が pending → success / error の遷移を視覚的に表示
SHOULDTanStack Query のキャッシュ整合性が E2E で検証されている
STOPキャッシュバグで Dogfooding 中にデータロスが発生したら H2 否定

H3 (インフラ): Aurora Serverless v2 + ECS Fargate でコスト・レイテンシ両立

Section titled “H3 (インフラ): Aurora Serverless v2 + ECS Fargate でコスト・レイテンシ両立”
区分条件
MUST1 週間連続稼働で API 5xx 率 < 0.1%
MUSTAPI p95 レイテンシ < 500ms(許容)/ 目標 < 300ms
MUST月額コスト < $100(許容)/ 目標 $80
SHOULDAurora Serverless v2 が 0 ACU まで scale-to-zero できている
STOPCold Start で p95 > 1s が常態化したら H3 否定
  • 全 H1 / H2 / H3 の MUST が満たされ、いずれの STOP にも該当しない場合 → Phase 2 (MVP) 移行 GO
  • いずれかの STOP に該当 → 該当仮説の再設計、もしくは PoC 中止
  • MUST の一部未達 → Dogfooding 延長 or 部分的に再設計

判定の運用は GitHub Tracking Issue で進捗管理する。

graph TD
Client["Next.js 15 (Vercel)<br/>TanStack Query / shadcn/ui"]
Auth["Clerk"]
API["Hono API (ECS Fargate)"]
DB[("Aurora Serverless v2<br/>PostgreSQL 15")]
Webhook["Clerk Webhook Receiver<br/>(同一 ECS サービス)"]
Client -- "JWT取得" --> Auth
Client -- "API (JWT)" --> API
API -- "JWKS検証" --> Auth
API -- "Drizzle" --> DB
Auth -- "user.created等" --> Webhook
Webhook -- "users同期" --> DB

技術スタック: Turborepo / Next.js 15 / React 19 / TanStack Query v5 / shadcn/ui + Tailwind / Hono / Clerk / Aurora Serverless v2 / Drizzle ORM / ECS Fargate / Vercel / Terraform

erDiagram
users ||--o{ objectives : "owns"
objectives ||--o{ key_results : "has many"
key_results ||--o{ tasks : "has many"
users {
uuid id PK
text clerk_user_id UK
text email
text display_name
timestamp deleted_at
timestamp created_at
timestamp updated_at
}
objectives {
uuid id PK
uuid user_id FK
text title
text description
timestamp start_date
timestamp end_date
integer version
timestamp deleted_at
timestamp created_at
timestamp updated_at
}
key_results {
uuid id PK
uuid objective_id FK
text title
numeric target_value
numeric current_value
integer version
timestamp deleted_at
timestamp created_at
timestamp updated_at
}
tasks {
uuid id PK
uuid key_result_id FK
text title
text status "CHECK (NOT_STARTED/IN_PROGRESS/DONE)"
integer version
timestamp deleted_at
timestamp created_at
timestamp updated_at
}

主要な設計ポイント(詳細は ADR 参照):

  • 独自 UUID + clerk_user_id 紐付け(ADR 007)
  • 論理削除は Read 時カスケード(ADR 008)
  • numeric(10,2) で浮動小数点丸め誤差回避
  • status は CHECK 制約(ENUM 変更困難を回避)
  • 楽観的ロック version 列 + UPDATE 時に 409 Conflict

ダッシュボード(/dashboard)に以下の UI 機能を実装済み:

操作UI実装パターン
作成テキスト入力 + 追加ボタン楽観的更新(invalidate)
タイトル編集インライン編集(クリックで入力に切替)楽観的更新(onMutate)
期間設定startDate / endDate の date input楽観的更新(onMutate)
進捗率表示子 KR の currentValue / targetValue 平均を集計、プログレスバー + %表示フロントエンド算出(DB カラムなし)
削除Undo トースト(5 秒猶予 + 取り消し)ADR 013
操作UI実装パターン
作成Objective 内インライン追加楽観的更新(invalidate)
タイトル編集インライン編集楽観的更新(onMutate)
進捗更新current / target クリックで数値入力に切替楽観的更新(onMutate, String() 変換)
プログレスバーcurrentValue / targetValue のバー表示フロントエンド算出
削除Undo トースト(5 秒猶予 + 取り消し)ADR 013 拡張
操作UI実装パターン
作成KR 内インライン追加楽観的更新(invalidate)
ステータス変更Badge クリックで NOT_STARTED → IN_PROGRESS → DONE サイクル楽観的更新(onMutate)
削除Undo トースト(5 秒猶予 + 取り消し)ADR 013 拡張
  • インライン編集: クリックで <span><input> に切替、Enter で確定、Escape でキャンセル
  • Undo トースト: プログレスバー付き。5 秒以内なら「元に戻す」で完全復元(API 未呼出)
  • View Transitions: ルート遷移(fade + blur + Y shift)、ヘッダーアンカリング、ロゴモーフィング(ADR 015)
  • デザイントークン: OKLCH 3 層構造(Primitive → Semantic → Tailwind)、ダークモード専用(ADR 010)

詳細は各 ADR を参照:

以下は PoC フェーズで意図的に簡略化し、Phase 2 (MVP) 移行時に詳細化する:

  • セキュリティ: Clerk JWT 検証 + WHERE user_id = $authUserId 必須化のみ。 STRIDE, CORS/CSRF 詳細, Rate Limiting は Phase 2 で検討
  • 観測: CloudWatch 標準のみ。Sentry, 分散トレーシングは Phase 2
  • テスト: 楽観的 UI の E2E (Playwright) のみ。Unit カバレッジ目標は Phase 2
  • コスト: 月額 ~$80(内訳は ADR 003 / ADR 004 参照)
  • Rollout/Rollback: PoC は Dogfooding のみ、切り戻し不要

9. Pre-mortem (PoC で頓挫するとしたら)

Section titled “9. Pre-mortem (PoC で頓挫するとしたら)”
  • A: 楽観的 UI のキャッシュキー設計バグで「保存されたように見えて未保存」が 頻発し、Dogfooding 段階で仮説 H1 / H2 が否定される
  • B: Aurora Serverless v2 の Cold Start で p95 300ms を恒常超過、仮説 H3 が否定される
  • C: 技術は成立するが、Dogfooding で「既存ツールと変わらない」と主観評価され仮説 H1 が否定される。 この場合、UI/UX を再設計するか、プロジェクト自体を中止する判断を行う
  • Q1. Webhook 受信失敗時の補償設計: user.updated / user.deleted 欠損時の 整合性回復方法(日次バッチで Clerk API から差分取得?)
  • Q2. DB マイグレーション運用: Drizzle migrations を CI/CD のどこで実行するか (ECS タスク更新前か後か)
  • Q3. Server Components と TanStack Query の責務分担: 初期データフェッチを どこまで Server Component で行い、どこから Client Component へ渡すか
  • Q4. 10,000 MAU 時のコスト試算: Phase 2 移行判断時に再試算
  • Q5. Integration Test の DB 戦略: pg_cron 拡張のテスト環境再現性

Phase 2 移行時の TODO (このドキュメントには書かない、別途作成する)

Section titled “Phase 2 移行時の TODO (このドキュメントには書かない、別途作成する)”
  • Non-Functional Requirements (SLO, RPO/RTO)
  • Success Metrics (定量的KPI)
  • Security 詳細 (STRIDE, CORS/CSRF, Rate Limiting)
  • Observability 詳細 (Sentry, 分散トレーシング)
  • Rollout & Rollback Plan
  • Cost 詳細試算 (10,000 MAU 時)
  • Testing Strategy 詳細 (カバレッジ目標、負荷試験)