ShukatsuHub | 最終発表

就活一元管理ダッシュボード ShukatsuHub

情報整理の手間を最小化し、浮いた時間を研究に充てる

SIOS インターンシップ 2026 / チームA / 2026-08-07

ShukatsuHub | 最終発表

本日の流れ(25分)

説明

  1. 中間発表からの到達点
  2. 課題とゴール(おさらい)
  3. 実装した機能
  4. 技術と品質

デモ

12機能すべてが動くところを通しで

質疑

中間発表で説明した背景・ペルソナ・デザイン選定は要点だけに絞り、追加実装と学びに時間を使います。

ShukatsuHub | 最終発表

1. 中間発表からの到達点

ShukatsuHub | 最終発表

中間発表で「最終に向けて」と言ったこと、その結果

機能 中間時点 現在
想定問答の生成 予定 実装済 AI 生成+準備率
選考ステータス管理ボード 予定 実装済 5列カンバン
ナレッジの蓄積 予定 実装済 メモ一覧・企業別
通知 予定 実装済 重要メール検知
面接対策収集 要検討 実装済 企業研究+規約調査レポート
Google カレンダー実連携 予定 実装済 OAuth2+候補日おすすめ
Gmail 実連携 予定になかった 実装済 OAuth2・本文を取らない権限設定
企業の発見・マッチング スコープ外と判断 実装済 判断を覆して追加

「定義が固まっていない」として一度は見送った企業マッチングを、条件と重み付けを決めきったうえで追加した。

ShukatsuHub | 最終発表

数字で見る到達点

289バックエンドのテスト
196フロントのテスト
12実装した機能
0型エラー
  • 中間発表時点:バックエンド 91 / フロント 75 / 画面 4
  • 実測(pytest -q 289 passed / vitest run 196 passed / tsc --noEmit エラー0)
  • API エンドポイント 28本、テストファイル 34本(バックエンド18・フロント16)

テストは「動くこと」ではなく「壊れ方」を決めるために書いた(AI が落ちても止まらない、同期を2回押しても増えない等)。

ShukatsuHub | 最終発表

2. 課題とゴール(おさらい)

ShukatsuHub | 最終発表

ペルソナ:佐々木 拓海(22歳・修士1年)

  • エントリー 20〜30社(ピーク時)
  • Gmail / iCloud / 求人サイト / Notion / スプレッドシート
    を手動で行き来している
  • 平日はゼミ、隙間時間にメール確認、夜に ES と面接対策
  • 休日が就活と課題で潰れる

中間発表で挙げた4課題
メールの見逃し/選考状況の把握/日程の転記
自己分析が面接準備に繋がらない

ゴール

情報整理と連絡対応の手間を最小化
浮いた時間を研究に充てる

そのため全画面の最上部に
「研究にあてられる時間」を常に置いた

ShukatsuHub | 最終発表

3. 実装した機能

ShukatsuHub | 最終発表

実装した機能の一覧(12機能)

# 機能 画面 中身
① 今日(ホーム) / 4指標・今日やること・返すべきメール・タイムライン・空きスロット
② カレンダー /calendar 週/月表示・衝突の可視化・同期・面接の候補日おすすめ
③ メールの自動振り分け /inbox 2アカウント統合・重要/確認/広告に分類・スレッド集約
④ プロフィール・自己分析 /profile 9項目の保存・コピー・充実度%
⑤ 想定問答 /qa AI 生成・回答の保存・準備率
⑥ タスク・締め切り /tasks 企業に紐づく締切・今日画面と空き時間に反映
⑦ 選考ステータス管理 /pipeline 5列カンバン・ドラッグ移動・状態タグ
⑧ 企業の発見・マッチング /companies マッチ率(計算)・受信箱からの企業登録
⑨ 企業研究 /interview 公開情報の収集・AI 整理・出典・確認観点
⑩ ナレッジ蓄積 /knowledge 面接振り返り・企業メモ・テンプレート
⑪ 通知 全画面 重要メール検知バナー・デスクトップ通知
⑫ 外部サービス連携 設定 Google カレンダー(OAuth2)/Gmail(本文を取らない権限)

①〜④が中間発表のスコープ。⑤〜⑫が最終発表に向けて追加した分。画面としては10枚、機能としては12。

ShukatsuHub | 最終発表

全体像:3タブ + 機能パネル7項目

  • 上部タブは3つ固定(今日 / カレンダー / 受信箱)。残りは ☰ 機能 パネルの7項目から遷移
  • 全項目が実ページを持つ(中間時点は9項目中2つだけが遷移可能だった)
  • 開かなくても状況が分かるよう、各項目にサブテキスト(充実度・準備率・メモ件数は実データ)
ShukatsuHub | 最終発表

① 今日(ホーム)

  • 開いたら今日の動きだけが分かる(4指標・今日やること・返すべきメール・タイムライン)
  • 空き時間に締切が最も近いタスクを1つずつ差し込む(空き 2h ― 説明会予習 をここに)
ShukatsuHub | 最終発表

② カレンダー + Google 連携

  • Google カレンダーの実連携(OAuth2)
  • 実際の予定がそのまま今日画面に出る
  • 同期 は何回押しても件数が増えない
  • 未認可ならモック同期に落ちる
  • 就活=ティール・学業=グレーで色分け

デモでは Google 側に予定を追加し、同期後に今日画面が変わるところをお見せします。

ShukatsuHub | 最終発表

③ メールの自動振り分け(受信箱)

  • Gmail は実連携(OAuth2)。
    iCloud はモックのまま 1つの箱にまとめ、企業・スレッド単位で畳む
  • 権限は gmail.metadata に限定し、
    本文を取得できないようにした
    (AI に本文を渡さない)
  • 件名のキーワードで重要/確認/広告
    に分類し、 判定できないものだけ AI に回す
  • AI 判定には AI バッジ
ShukatsuHub | 最終発表

④ プロフィール・自己分析

  • ガクチカ・強み・自己PR など
    9項目を1か所
    に保存
  • コピーボタンで ES やマイページに貼れる
  • 未入力の項目名を名指しし、
    充実度%で 準備の進み具合を出す
ShukatsuHub | 最終発表

⑤ 想定問答

  • プロフィール+企業情報から、AI が
    想定質問と回答骨子を生成する
  • 同じ企業で何度生成しても
    件数が増えない
  • 回答を保存すると準備済みになり、
    準備率で進み具合が見える
ShukatsuHub | 最終発表

⑥ タスク・締め切り

  • 企業に紐づく締切を1か所で管理する
  • ここで登録した締切が
    今日画面と空き時間に表示
  • 完了しても行が動かず打ち消し線になる
    (探し直しが起きない)
  • 期限を過ぎた未完了は色を変えて示す
ShukatsuHub | 最終発表

⑦ 選考ステータス管理ボード

  • 気になる / エントリー / 書類選考 / 面接 / 最終・内定
    の5列カンバン
  • カードはドラッグで列を移動
  • 状態タグ(ES 本日 / 結果待ち N日)で
    急ぎのカードが目に入る
  • 締切はタスク画面と共通
ShukatsuHub | 最終発表

⑧ 企業の発見・マッチング(追加実装)

  • テンプレ質問に答えると、
    マッチ率つきで企業が並ぶ
  • マッチ率は AI ではなく計算
    職種3・勤務地2・年収2
    休日1・リモート1・軸1
  • 合致した条件だけを理由に出す
ShukatsuHub | 最終発表

なぜマッチ率に AI を使わなかったか

AI に出させると、同じ条件でも実行のたびに数字が変わる
→
重み付きの純関数にして、
同じ入力なら常に同じ結果にした
  • 「なぜ 78% なのか」をその場で説明できることを優先した(ユーザーにも発表でも)
  • 年収・休日は AI に生成させない。
    企業に保存した値だけを使い、画面に並記して照合できるようにした
  • 企業側が未登録の項目は合致しない扱い(推測で埋めない)
ShukatsuHub | 最終発表

⑨ 企業研究(情報収集)

  • 企業の公開ページを取得し、AI が
    事業・求める人材・働き方・最近の動きに整理する
  • すべての行に出典リンクを付け、
    AI 生成であることを明示
  • 「事業の柱を3つ言えるようにする」など、
    確認観点をチェックリストで残す
ShukatsuHub | 最終発表

「規約に違反しないか」を先に調べた

  • robots.txt を確認/取得は4ページ・1秒間隔
  • 著作権法30条の4(情報解析)と引用の要件を整理
  • Azure OpenAI は入力を学習に使わない

成果物

docs/compliance-ai-web-collection.md

一次情報(規約・法令・行政文書)に当たり、 判断が必要な点を人に返す

「動くから良い」ではなく「使ってよいか」を先に確かめる、という進め方をした。法的な最終判断は人が行う前提で書いている。

ShukatsuHub | 最終発表

⑩ ナレッジ蓄積

  • 面接振り返り・企業メモ・テンプレート・学びを カテゴリ別に蓄積
  • 企業に紐づけて残せるので、
    次の選考の準備にそのまま使える
ShukatsuHub | 最終発表

機能はつながって初めて効く

メールが届く
→
受信箱が自動で分類
→
未登録の企業を検出
→
1クリックで選考ボードへ
面接が決まる
→
締切をタスクに登録
→
今日画面と空き時間に反映
→
企業研究と想定問答で準備
  • 手で転記する場面をなくすのが狙い(分からない項目は空のままにして推測で埋めない)
  • プロフィールの就活軸は、マッチングと想定問答の両方が入力元として使う
  • どの画面でも最上部の指標は共通。手間を減らすと研究時間が増えるが一貫して見える
ShukatsuHub | 最終発表

4. 技術と品質

ShukatsuHub | 最終発表

全員が未経験だった2つの技術

① API を通した AI の利用

  • Azure OpenAI(Responses API)
    Chat Completions 形式では response_format が使えず 400。
    SDK の定義を読んで方式ごと切り替えた
  • 構造化出力:JSON を自前でパースせず
    Pydantic の型で受け取る
  • 落ちない設計:キー未設定・通信失敗・refusal は 例外を投げずフォールバック

② Google APIとの連携

  • Google Calendar API:OAuth2 の認可・state 照合・ PKCE・トークン更新まで実装
  • Gmail API:権限を gmail.metadata に絞り、
    本文を取得できない状態で分類に使う
  • トークンを応答・ログに出さない。
    未認可なら seed に落ちて画面は止まらない

どちらも「動いた」で終わらせず、失敗した理由と選び直した理由を docs/decisions.md に残した。ほかに FullCalendar・TanStack Query・Marp も今回初めて使った。

ShukatsuHub | 最終発表

AI への指示は「文書の階層」で与えた

文書 役割 量
docs/spec.md 唯一の正(北極星)。画面・処理・データ・受け入れ条件 1,226行
CLAUDE.md AI が毎回読む運用ルール(禁止事項・触ってよいファイル・手順) 315行
guardrail.md 人が読むチームの運用ルール 319行
docs/decisions.md 決定と失敗の記録(なぜそうしたか) 280行
.claude/skills/spec feature 仕様を作る/実装〜テストを回す手順書 95行
.claude/agents/code-reviewer integrator レビュー役・統合役のサブエージェント定義 161行
.claude/settings.json 実行を許さないコマンド(git push 等)の定義 —
  • 迷ったら上から順に従うと決めた。仕様と実装が食い違ったらどちらを直すかは人が決める
  • AI に自分の制約を変えさせない。ルール文書の変更は人の明示的な指示があるときだけ
  • 検査役(code-reviewer)は指摘だけして修正しない。承認欲しさに問題を隠すのを防ぐため
ShukatsuHub | 最終発表

技術スタックと、やらなかったこと

層 技術
Backend Python 3.11 + FastAPI / SQLModel + SQLite
Frontend React + Vite + TypeScript / TanStack Query / 素の CSS
カレンダー UI FullCalendar / 日付計算 date-fns
AI Azure OpenAI(Responses API・構造化出力)
外部連携 Google Calendar API(OAuth2)
テスト pytest / Vitest(jsdom+Testing Library)

やらないと決めたこと:ユーザー認証・ログイン、Docker 化・CI・デプロイ、
UI ライブラリの導入(デザインモックのクラス語彙をそのまま移植するため素の CSS を選んだ)

ShukatsuHub | 最終発表

AI への設計図:ディレクトリ構成を先に決めた

開発初日にコンフリクトが多発して時間を失ったため、「誰がどのファイルを触るか」が
衝突しない構成を先に決め、それを AI への設計図にした。

backend/

main.py      ルータ登録(1行ずつ足す)
models.py    テーブル定義(spec §6 と1対1)
db.py        エンジンとセッション
routers/     API(機能ごとに1ファイル)
services/    ロジック(DB もネットも触らない)
seed/        ダミーデータ(JSON)+投入
tests/       pytest(機能ごとに1ファイル)

frontend/src/

App.tsx      ルート定義(1行ずつ足す)
pages/       画面(1機能1ファイル)
components/  Shell / Hero / 各ダイアログ
api/         TanStack Query のフック
lib/         表示ロジック(純関数・テスト対象)
styles/      tokens / shell / components

機能を1つ足すときに触るのは「routers に1つ・services に1つ・pages に1つ・tests に1つ」だけ。
担当が分かれてもファイルが重ならないので、12機能を並行して足しても構成が崩れなかった。

ShukatsuHub | 最終発表

AI は3箇所だけ。落ちても止まらない

使う場所

  • メール分類(ルールで決まらないものだけ)
  • 想定問答の生成
  • 企業研究の整理(最終発表で追加)

それ以外は使わない

失敗したときの落ち先

  • キー未設定・通信失敗・refusal
    → 例外を投げずフォールバック
  • メール分類 → 確認
  • 想定問答 → テンプレ質問
  • 企業研究 → seed のテンプレ(template)
  • 呼び出しは services/ai.py に集約

メール分類に本文は渡さない(件名と送信元のみ)。AI に渡す情報も最小限にしている。

ShukatsuHub | 最終発表

テストの考え方

289バックエンド
196フロント
34テストファイル
0型エラー
  • AI と Google は必ずモックする。テストで実 API を叩かない(結果が毎回変わるため)
  • 検証するのは壊れ方:同期を2回押しても増えない/キーが無くても落ちない/
    トークンを応答に含めない/条件0個なら企業を出さない
  • 緑にするために期待値を実挙動へ書き換えないをチームのルールにした
ShukatsuHub | 最終発表

5. デモ(8分)

ShukatsuHub | 最終発表

デモの流れ

# 画面 見どころ
1 今日 4指標・タスク完了で空き時間が増える・重要メールのバナー
2 カレンダー Google に予定を追加 → 同期 → 今日画面に反映・候補日おすすめ
3 受信箱 2アカウント統合・自動分類・フィルタ・AI バッジ
4 選考ステータス/タスク カンバン移動・企業追加・締切
5 企業マッチング 条件→マッチ率と理由・受信箱からの企業登録
6 企業研究/想定問答 出典つきメモ・AI 生成・準備率
7 プロフィール/ナレッジ 9項目・充実度・メモ
ShukatsuHub | 最終発表

6. 苦労した点と学び

ShukatsuHub | 最終発表

(1)同じ骨組みを2人で作った

2人が別々に土台を作り、同じものが2箇所にできた
→
共通基盤は1人が先に作り、他は待つ運用に変更
  • Git は置き場所が違うと衝突として検知しない。マージは成功するのに中身が二重になった
  • 原因は「機能の担当は決めたが、共通の土台の担当を決めていなかった」こと
  • 対策:着手前に git ls-tree origin/main で既存ファイルを確認する手順をルール文書に明記した
ShukatsuHub | 最終発表

(2)AI 基盤を途中で差し替えた

用意できたのは Anthropic ではなく Azure OpenAI の資格情報だった
→
呼び出しを1ファイルに集約していたので差し替えが1箇所で済んだ
  • Chat Completions 形式では response_format が使えず 400 エラー → Responses API に変更
  • 想像で書かず、SDK の実際の定義を確認してから実装し、実キーで疎通も確認した
  • 学び:外部サービスの差し替えは起きる前提で、呼び出しを1箇所に閉じ込めておく
ShukatsuHub | 最終発表

(3)仕様書と実装のズレは必ず起きる

パネルの項目を減らしたのに、仕様書は9項目のまま
→
仕様書を直すまでを1つの作業として扱う
  • 画面の「気になるに追加」が押しても何も起きない不具合も、この確認で見つかった
    (選考段階と登録フラグという別の意味の項目を取り違えていた)
  • 直したうえで「押したら何を送るか」のテストを足し、修正前のコードで赤くなることまで確認した
  • 学び:仕様書が正であり続けるように、実装を変えたら同じコミットで仕様書も直す
ShukatsuHub | 最終発表

AI 駆動開発をやってみて

効いたこと

  • 仕様書を先に固める(実装の迷いが消える)
  • レビュー役を分け、指摘する人と直す人を分離
  • 決定と失敗を docs/decisions.md に記録
  • ルール文書を AI が勝手に変えない制約

難しかったこと

  • 仕様に無いことをそれらしく作ってしまう
  • 数値・API 名のもっともらしい捏造
  • 対策:根拠をファイル名と行番号で示す、
    実在を確認してから使う、を明文化
ShukatsuHub | 最終発表

残っている課題

項目 状態
停滞企業の検出(通知②) 未実装 設計のみ残した
企業データの実データ連携 未着手 差し替え口だけ用意(company_source.py)
iCloud メールの実連携 未着手 モック JSON で代替中(Gmail は実連携済み)
認証・複数ユーザー対応 対象外 ローカル単一ユーザー前提

「できていないこと」を隠さずに残すことも、仕様書とチームのルールに含めた。

ShukatsuHub | 最終発表

中間発表でいただいたご指摘への回答

ご指摘 回答
AI の技術スタックを詳しく Azure OpenAI の Responses API。.env のデプロイ名指定・構造化出力・1回リトライ後フォールバック(24枚目)
AI に渡す個人情報は 件名と送信元のみ。本文は渡さない。Gmail の権限も gmail.metadata に限定(13枚目)
開発で AI に課したルールを詳しく 仕様書を頂点にした文書の階層で指示。ルール文書は AI に変更させない(25枚目)
技術挑戦の可視化 全員未経験だった2つ(AI の API 利用・Google 連携)として明示(24枚目)
苦労した点・開発状況の可視化 失敗3件とその仕組み化を章立てで(33〜36枚目)。決定と失敗は docs/decisions.md に12件記録
想定問答の作り方の明示 プロフィール+企業情報から生成し、準備率で進捗を出す(15枚目)
メールが溜まると分類精度は ルール判定は正規表現なので劣化しない。取得も直近100件・14日以内に限定している
予定表に入れない予定(友人との食事など) 未対応。空き時間から差し引けないため、実運用では過大に出る
モバイルでも使えると便利 スマホ幅を想定した設計にしているが、ローカル開発のため実機検証はできていない
Claude への依存割合 実装のほとんどは AI が書き、人は仕様・判断・レビューを担当。PR 31本すべて人が承認した
ShukatsuHub | 最終発表

まとめ

就活の手間を減らし、研究の時間を取り戻す

  • ペルソナを1人に絞り、その人の時間を返すことを基準に機能を選んだ
  • 中間の3機能から 12機能・10画面へ広げ、テストは 91→289 / 75→196 に増えた
  • 説明できることを優先した(マッチ率は計算、AI 出力には出典、規約は先に調査)
  • 失敗と決定を記録し、チームのルールとして残した

ご質問をお願いします

最終発表スライド(25分:スライド14分+デモ8分+質疑3分)。 出典は docs/spec.md / docs/decisions.md / docs/compliance-ai-web-collection.md + 実測値。 出力: npx @marp-team/marp-cli slides/final.md --theme slides/theme.css --pdf --allow-local-files -o slides/final.pdf 画像は slides/img/final/ に置く(_local/slides/最終発表/photo からコピーする)。 未検証の数値・未実装の機能を「できている」と書かない。発表直前に実測値へ更新する。

時間が押したら飛ばす(中間発表で説明済み。デモで触れる)

時間が押したら飛ばす(デモで触れる)

時間が押したら「素の CSS」と「やらないこと」だけ口頭で触れて次へ