AI Dev Lab
IndiePurse

IndiePurse ができるまで — フリーランスの手取りを試算する

フリーランスの手取り計算ツールの開発ログ。自治体別の国民健康保険料(所得割+均等割+平等割)や国民年金、個人事業税を積み上げる計算エンジンの設計を記録しています。

「フリーランスになったら、売上のうちいくら手元に残るの?」

会社員から独立するとき、多くの人がここで不安になります。会社員なら額面と手取りの差はだいたい把握できますが、個人事業主は所得税・住民税・国民健康保険・国民年金・(場合によっては)個人事業税と、引かれるものが多く、しかも国保は住む自治体で額が違う。全部足すといくらになるのか、見当がつかない。

IndiePurse は、売上と経費を入れると「実際に残る手取り」を出すシミュレーターです。フリーランス特有の負担を全部乗せて、ブラウザの中だけで計算します。


#🎯 会社員の計算ツールでは足りない

世の中の手取り計算ツールの多くは会社員向けで、社会保険料が給与から天引きされる前提です。フリーランスはこれが根本的に違います。

  • 健康保険 → 国民健康保険(自治体ごとに料率が違う、家族の人数でも変わる)
  • 年金 → 国民年金(定額、人数分)
  • さらに 個人事業税(業種と所得によってかかる)
  • 青色申告特別控除(最大 65 万円)で税額が大きく変わる

これらを会社員向けツールに当てはめても、まったく合いません。フリーランスの手取りは、フリーランスの構造で計算する必要があります。


#🏗️ 引かれるものを 1 つずつ積む

IndiePurse の計算は、「売上 − 経費」から出発して、負担を順番に引いていく構造です。

#所得税(累進・速算表)

まず所得税。会社員と同じ累進課税ですが、課税所得の出し方が違います。

ts
const INCOME_TAX_BRACKETS = [
 { upTo: 1_950_000, rate: 0.05, deduct: 0 },
 { upTo: 3_300_000, rate: 0.1, deduct: 97_500 },
 { upTo: 6_950_000, rate: 0.2, deduct: 427_500 },
 { upTo: 9_000_000, rate: 0.23, deduct: 636_000 },
 { upTo: 18_000_000, rate: 0.33, deduct: 1_536_000 },
 { upTo: 40_000_000, rate: 0.4, deduct: 2_796_000 },
 { upTo: Infinity, rate: 0.45, deduct: 4_796_000 },
]

function incomeTax(taxable: number): number {
 if (taxable <= 0) return 0
 const b = INCOME_TAX_BRACKETS.find((x) => taxable <= x.upTo)!
 return Math.max(0, taxable * b.rate - b.deduct)
}

国税庁の速算表そのままです。税額 = 課税所得 × 税率 − 控除額 で累進を一発計算します。

#青色申告特別控除

フリーランスの税金で一番効くのがこれです。

ts
export const AOIRO_OPTIONS = [
 { id: "e65", label: "青色 65 万 (e-Tax / 電子帳簿)", value: 650000 },
 { id: "p55", label: "青色 55 万 (紙)", value: 550000 },
 // ...
]

複式簿記で記帳し、e-Tax で申告すると 65 万円を所得から差し引けます。これは経費が 65 万円増えるのと同じ効果で、課税所得を直接押し下げます。青色申告を選ぶかどうかで、手取りが数十万円変わることも珍しくありません。

#国民健康保険(自治体別)

ここが会社員向けツールにない、最も面倒な部分です。国保は 自治体ごとに料率が違い、しかも「医療分・後期高齢者支援分・介護分」の 3 階建てになっています。

ts
export const KOKUHO_PRESETS: KokuhoPreset[] = [
 // 東京23区 / 大阪 / 横浜 / 名古屋 / 福岡 / 全国平均 ...
]

function kokuhoTier(base: number, members: number, households: number, t: KokuhoTier): number {
 // 所得割 + 均等割(人数) + 平等割(世帯) を上限つきで合算
 ...
}

国保料は「所得割(所得に比例)+ 均等割(加入人数に比例)+ 平等割(世帯ごと)」を足し、自治体ごとの上限で頭打ちにする構造です。IndiePurse は主要都市+全国平均をプリセットとして持ち、選ぶだけで近い額が出るようにしました。介護分(40〜64 歳)も年齢で自動的に加わります。

#国民年金・個人事業税

年金は定額です。

ts
export const NENKIN_MONTHLY = 17510 // 円/月・人 (2025 年度)

人数分を掛けるだけ。個人事業税は業種によって税率が違い(多くは 5%)、事業所得が一定額(290 万円)を超えた分にかかります。業種を選ぶと自動で判定します。


#😓 苦労したところ

#「国保が自治体で違う」をどう扱うか

正確を期すなら、全国 1,700 以上の市区町村の料率を持つ必要があります。現実的ではありません。かといって「全国一律」にすると、国保が最も大きな負担の一つである以上、外し方が大きくなる。

折衷案として、主要都市+全国平均のプリセットにしました。自分の自治体がなくても「全国平均」で大枠は掴めるし、近い規模の都市を選べば実額に寄せられる。完全な正確さは諦めて、「桁を外さない」ことを優先した判断です。画面には「正確な額は自治体で確認を」と明記しています。

#現金ベースと税務ベースのズ레

「売上 − 経費」は現金の手残りに近い一方、税金の計算に使う「事業所得」は青色控除などを引いた後の額です。この 2 つを混同すると、手取りの計算が合わなくなる。

そこで内部では「税額計算用の課税所得」と「実際の手残り」を別々に持ち、最後に『手取り = 売上 − 経費 − (所得税+住民税+国保+年金+事業税)』で合流させています。控除は税金を減らすだけで、現金が増えるわけではない——この当たり前を、計算の流れとして正しく反映するのが地味に大事でした。

#概算だと正直に書く

税額は、医療費控除・小規模企業共済・配偶者の状況など、個別事情で変わります。IndiePurse の数字を「確定額」と受け取られると、独立の判断を誤らせかねない。

なので、代表的な料率・控除での概算であること、正確な額は税務署・自治体で確認することを、はっきり書いています。お金の判断に関わるツールでは、精度の限界を隠さないことが信用の条件だと考えています。


#🔭 今後の拡張

  • 小規模企業共済・iDeCo — フリーランスの代表的な節税枠を控除に反映
  • 消費税(インボイス) — 売上 1,000 万円超・課税事業者の消費税負担
  • 会社員との比較 — 「同じ額を稼ぐなら会社員 vs フリーで手取りはどう違うか」
  • 自治体の追加 — プリセット都市を増やす

#💡 このサービスから言えること

「会社員向け」と「フリーランス向け」は、同じ手取り計算でも別物。 天引きされる社会保険と、自分で払う国保・国民年金では、構造がまるで違います。既存の計算ツールをフリーランスに流用しても合わないのは、この構造の違いを吸収していないからでした。

もうひとつは、正確さと実用性のトレードオフです。国保料を全自治体分正確に持つのは非現実的ですが、だからといって諦めるのではなく「主要都市+平均で桁を外さない」ところに落とす。完璧を目指して作れないより、割り切って役に立つほうを選ぶ——お金のシミュレーターを作るたびに向き合う判断です。そして、独立という大きな決断に関わる数字だからこそ、できることとできないことを正直に示すことが、何よりの機能だと思っています。

[ ./next_action ]

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

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

[ ./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 →