AI Dev Lab
RaiseDraft

RaiseDraft ができるまで — 給与交渉メールの草案を作る

昇給交渉メールの下書き生成ツールの開発ログ。 11 業種 × 5 経験年数 × 4 職位 = 220 通りの相場データを用意し、 希望額が相場から見て妥当かを 4 段階で判定して文面を切り替える設計を記録しています。

·decision改善·stage公開中

RaiseDraft は 給与交渉 草案 ジェネレーター。 業種 × 経験年数 × 職位 から 年収相場 (下位 25% / 中央値 / 上位 25%) を表示、 4 トーン (やんわり打診 / 直接的 / 数字で押す / 感情訴求) で 上司向け 交渉メール本文を 自動生成。 ラボ 39本目、 ジェネレーター ジャンル 5本目 (JargonScope 用語リライト / LeapBio キャリアサマリ / PitchEdge 営業切返し / StackTale 副業提案 / RaiseDraft 給与交渉、 キャリア収入 文面 5 本 で 入社 → スキル → 提案 → 副業 → 交渉 が連続)。

#なぜこの形にしたか

外部 AI の 90+α 提案リストから 「無料で運営できて (¥0/月)、 PV ボリュームが大きい」 候補のうち、 GradFund (教育費) の次に 検索ボリュームが大きく かつ 純 JS + 静的 DB で完結する案として 案 22 「給与交渉代行」 を選定。 「給与交渉 メール」 「年収交渉 文面」 「昇給 依頼 メール」 系の検索意図 は 「具体的な文章テンプレが欲しい」 が中心で、 静的なテンプレ + 業種別 相場 + 動的入力反映 で 十分応えられる。 同時に 業種別 相場 表示は それ単独でも 滞在価値があり、 SEO 二重採取 可能。

#技術スタック

#11 業種 × 5 経験 × 4 職位 = 220 セルの相場 DB

ts
const INDUSTRIES: IndustryInfo[] = [
 { id: "it-engineer", label: "IT エンジニア", bandsByExp: {
 "0-2": [350, 420, 500], // [下位25%, 中央値, 上位25%] 万円
 "3-5": [450, 550, 680],
 "6-9": [560, 700, 880],
 "10-14": [650, 820, 1050],
 "15+": [750, 950, 1300],
 }},
 // ... 11 業種
]

const POSITION_MULTIPLIER = {
 general: 1.0, leader: 1.12, manager: 1.28, director: 1.55,
} as const

// 最終 bands = baseRange × position 係数

ソース: 厚生労働省 賃金構造基本統計調査 (令和 5 年) + doda / マイナビ / リクナビ NEXT の 職種別 公開データ。 220 セルを 手打ちで タイポしない構造 (TypeScript の Record<Experience, [number, number, number]> で 型レベル 強制)。

#4 トーン メールテンプレ

ts
function buildEmail(input: CalcInput, bands: Bands) {
 switch (input.tone) {
 case "soft": // 関係維持 + 相談ベース
 case "direct": // 数字明示 + 評価面談タイミング
 case "data": // 表組 + 相場比較 + KPI
 case "emotional": // 成長意欲 + 「もっと貢献したい」
 }
}

トーンごとに 件名 + 本文 を まるごと差し替え (4 個の 独立テンプレ)。 共通変数 (上司名 / 自分名 / 数字 / 実績リスト) は どのトーンにも 同じインターフェイスで注入。 「数字で押す」 トーンだけ ASCII 罫線 で 表組を作って 数字を縦に並べる構造に。

#4 段階 verdict 判定

ts
function verdict(diffPct: number) {
 if (diffPct < 0.05) return { v: "modest", label: "控えめ" }
 if (diffPct < 0.12) return { v: "fair", label: "妥当" }
 if (diffPct < 0.25) return { v: "ambitious", label: "攻めの姿勢" }
 return { v: "stretch", label: "ストレッチ" }
}

verdict は CSS の data-verdict 属性に流して、 バックグラウンド色を sage (控えめ) / navy (妥当) / brass (攻め) / vermillion (ストレッチ) に切替。 数字を 「読まなくても」 配色で 状況が分かる。

#見た目の方針

ビジネス便箋 + 万年筆 + 朱印 モチーフ:

  • 配色: ivory letter paper #fafaf2 + slate navy #2a3a5a + brass nib #b89240 + 朱印 vermillion #c63224 + sage rule #6a8a6a + sky tag #4f6f9a
  • モチーフ: 上部 navy headBar + brass nib ✒ icon + ivory 便箋 letterhead + 朱赤 verdict 「判定」 stamp + dashed sage 罫線 + sage left-rule の note
  • typography: Instrument Serif italic (正式書状 feel) + Space Grotesk 800 (display) + JetBrains Mono (numerics + 出力 pre)

既存 ジェネレーター 4 本 (JargonScope cyan terminal / LeapBio purple resume / PitchEdge red battle / StackTale emerald market) とも、 マネー計算機 6 本 (CoinStack midnight navy / RoofFund cyan blueprint / GiftCap 墨朱 / SideTax ledger green / StorkCast 母子手帳 / GradFund parchment maroon) とも完全別軸。 唯一の 「ビジネス便箋 + 万年筆」 モチーフ。

#6 プリセット

  • IT エンジニア 5 年目 / leader / 妥当な昇給 (12.7%) / data トーン
  • 営業 3 年目 / general / やんわり相談 (14.3%) / soft トーン
  • コンサル 10 年目 / manager / 直接交渉 (25%) / direct トーン
  • デザイナー 7 年目 / leader / 感情訴求 (15.4%) / emotional トーン
  • マーケ 6 年目 / leader / 攻めの昇給 (21.7%) / data トーン
  • 新人 2 年目 / general / 控えめ昇給 (5.7%) / soft トーン

#まだやっていないこと

  • 会社規模 (大企業 / 中堅 / ベンチャー / 外資) による 相場補正
  • 転職オファー 持参 モード (希望年収の根拠に 他社オファー を入れる)
  • 昇給率 シミュ (1 年後 / 3 年後 / 5 年後 の 想定キャリア年収)
  • 逆面談 想定 Q (「なぜ今その金額か」 「業績 貢献 を 数値で」 を 想定問答)
  • メール送信タイミング カレンダー (期初 / 期末 / 評価面談 前後 の最適日)
  • 英語版 トーン (外資系 向け 英文 テンプレ)

[ ./next_action ]

読んだら、 RaiseDraft を実際に動かす。

この開発ログは RaiseDraft をどう作ったかの記録です。 読み終わったらそのままサービス本体へ戻って、 実物で価値を確かめてください。

[ ./related_logs ]

関連する開発ログ

all logs →
ToonCast

ToonCast ができるまで — AnimeGANv2 をブラウザで動かす

AnimeGANv2 の小さな ONNX (約9MB) を onnxruntime-web (単一スレッド WASM=COOP/COEP不要、 color-revive で承認済みライブラリの再利用) で実行。 512x512・[-1,1] 正規化で推論し、 結果を元解像度に戻して表示する設計記録。 写真は端末内処理。

read log →
ColorRevive

ColorRevive ができるまで — onnxruntime-web で白黒写真をカラー化

DeOldify の量子化 ONNX を onnxruntime-web (CDN side-load・単一スレッド WASM=COOP/COEP不要) で実行。 256x256 でモデル推論し、 輝度は元写真・色だけ AI を YCbCr で再合成して輪郭を保つ設計記録。 写真は端末内処理。

read log →
PhotoTwin

PhotoTwin ができるまで — CLIP画像埋め込みで似た写真を見つける

CLIP (Xenova/clip-vit-base-patch32) の image-feature-extraction を transformers.js の CDN ESM で side-load し、 各写真を正規化ベクトル化。 cosine 類似度で重複・似た写真をブラウザ内で検出する設計記録 (新ライブラリ追加なし=what-cam と同じ CLIP の再利用)。

read log →
AkinFind

AkinFind ができるまで — ブラウザ内で完結する embeddings 意味検索

多言語の文章埋め込みモデル (Xenova/multilingual-e5-small) を transformers.js の CDN ESM で side-load し、 各文を正規化ベクトル化。 cosine 類似度で意味検索と似ている文ペア検出を全て端末内で行う設計記録。

read log →
WhatCam

WhatCam ができるまで — CLIP のゼロショット画像分類をブラウザで動かす

CLIP (Xenova/clip-vit-base-patch32) を transformers.js の CDN ESM で side-load し、 写真と候補ラベルの近さをブラウザ内で計算。 日本語ラベルを英語プロンプトに変換し、 図鑑と自由入力の両モードで「これ何?」を判定する設計記録。

read log →
DepthCast

DepthCast ができるまで — 1枚の写真をAIの深度推定で立体にする

Depth Anything (transformers.js) を CDN ESM で side-load し、 1枚の写真から深度マップを推定。 WebGL2 フラグメントシェーダで深度に比例した視差 (iterative backward parallax) を作り、 赤青アナグリフ / WebM 書き出しまで端末内で完結させた設計記録。

read log →