「3つの数字」で考える14日納品のアーキテクチャ判断
私たちのチームでは、すべてのソフトウェアプロジェクトを 3つの数字 で説明しています。
- $0 — 初回プロジェクトの請求額
- 14日 — キックオフから本番納品までの日数
- 100% — クライアントの GitHub に譲渡するソースコードの割合
この記事では、この3つの数字を マーケティング上のスローガン ではなく、エンジニアリング上の制約
として扱うとき、アーキテクチャと開発フローにどんな影響が出るかを書きます。
結論先出し — 3つの数字を「コード」で担保する5原則
- $0 を成立させるには「営業工程をコードに置き換える」 — 自動スコーピング、テンプレ・スキャフォールド、デモ環境の自動生成
- 14日 を成立させるには「Day 0 で全テーブル定義を完了させる」 — スキーマ後付けは時間的に不可能
- 14日 × 本番品質 を成立させるには「型システムと CI を厳格化する」 — 人間のレビュー時間を最小化
- 100% 譲渡を成立させるには「自社固有ライブラリ依存を作らない」 — オープンソース・標準的なスタックを優先
- MVPではない を成立させるには「Day 12 を専用QAデーにする」 — 機能追加ではなく品質確認のための1日
順に、コードと判断根拠を見ていきます。
- $0 の成立条件 — 営業工程をコードに置き換える
伝統的な開発会社は売上の 25〜40%
を営業・提案・契約のプロセスに使います。この工程を残したまま「初回無料」をやると、単純に赤字になります。
私たちは 営業の代わりにコードを書いた だけです。
1-1. 自動スコーピング — スプレッドシートではなく型で定義
❌ Bad: Word ドキュメントの SOW を毎回手作業で書く
- ユーザー登録機能
- マイページ機能
- 管理画面
- 決済機能
- …
✅ Good: TypeScript の型としてスコープを定義する
// scope/intake.ts
export const ProjectScope = z.object({
auth: z.object({
providers: z.array(z.enum(['email', 'google', 'github', 'apple'])),
mfa: z.boolean(),
passwordReset: z.literal(true), // 必ず含める
}),
payments: z.object({
provider: z.enum(['stripe', 'paypal', 'none']),
recurring: z.boolean(),
invoices: z.boolean(),
}),
dashboards: z.array(
z.object({
name: z.string(),
widgets: z.array(z.enum(['table', 'chart', 'kpi', 'export'])),
}),
),
// …以下、機能ごとに型で定義
});
export type ProjectScopeT = z.infer;
これにより:
- 「スコープに入っているか」が コンパイル時に検証可能
- スキャフォールド・テスト・ドキュメント生成がすべて 同じ型を参照
- 営業時間を コード生成時間 に置き換えられる
1-2. デモ環境の自動プロビジョニング
$0 で動くものを見せるには、デモ環境を 手作業で立てない ことが必須です。
// scripts/provision-demo.ts
async function provisionDemo(scope: ProjectScopeT) {
const projectId = generateProjectId();
await Promise.all([
createSupabaseProject(projectId, scope),
createVercelDeployment(projectId, scope),
createStripeTestKeys(projectId),
seedDemoData(projectId, scope),
]);
return { previewUrl: https://${projectId}.demo.example.dev };
}
この provision-demo が 5分以内 に完了することが、$0 を成立させる前提条件です。
- 14日 の成立条件 — Day 0 で全テーブル定義を完了させる
❌ Bad: 機能ごとにスキーマを後から足していく
// Day 1
const users = pgTable('users', { id, email });
// Day 5
const posts = pgTable('posts', { id, userId, content });
// Day 9 — ⚠ ここで「メンバーシップが必要」と判明
// → users と posts の両方にマイグレーションが発生
// → 既にできているフロントエンドの再修正が発生
このパターンは Day 9 のスキーマ変更が 3〜5 日分の作り直し を引き起こし、14日スケジュールが破綻します。
✅ Good: Day 0 で全テーブルを定義する
// schema/index.ts — Day 0 で完成させる
import { pgTable, uuid, text, timestamp, integer, boolean, pgEnum } from 'drizzle-orm/pg-core';
export const roleEnum = pgEnum('role', ['admin', 'member', 'viewer']);
export const planEnum = pgEnum('plan', ['free', 'pro', 'enterprise']);
export const organizations = pgTable('organizations', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name').notNull(),
plan: planEnum('plan').notNull().default('free'),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
organizationId: uuid('organization_id')
.notNull()
.references(() => organizations.id, { onDelete: 'cascade' }),
email: text('email').notNull().unique(),
role: roleEnum('role').notNull().default('member'),
emailVerifiedAt: timestamp('email_verified_at'),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
// …以下、全テーブルを Day 0 で完成
Day 0 でスキーマを固定するメリット
┌──────────────────────┬───────────────────┬────────────────────────┐
│ 項目 │ Day 0 確定 │ 後付け │
├──────────────────────┼───────────────────┼────────────────────────┤
│ マイグレーション回数 │ 1〜2回 │ 10回以上 │
├──────────────────────┼───────────────────┼────────────────────────┤
│ フロント再修正コスト │ ほぼ0 │ スキーマ変更ごとに発生 │
├──────────────────────┼───────────────────┼────────────────────────┤
│ デプロイダウンタイム │ 0 │ 移行ごとに発生 │
├──────────────────────┼───────────────────┼────────────────────────┤
│ 認知負荷 │ 1回で全体を考える │ 毎日「次は何を直す?」 │
└──────────────────────┴───────────────────┴────────────────────────┘
「設計に時間をかける」ではなく、「設計を1日に圧縮する」 が 14 日納品の前提です。
- 14日 × 本番品質 の成立条件 — 型と CI を厳格化する
14日で本番品質を出すには、人間のレビュー時間を最小化する
必要があります。これは「レビューしない」ではなく、「機械が見るところは機械に任せる」 という意味です。
CI で必ず落とすルール(提案)
.github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- uses: actions/setup-node@v4
with: { node-version: '20', cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
# 1. 型チェック (no any, no implicit any, strict mode)
- run: pnpm tsc --noEmit
# 2. ESLint (eslint-config-strict + no-explicit-any)
- run: pnpm lint --max-warnings=0
# 3. テスト (カバレッジ閾値あり)
- run: pnpm test --coverage --coverage.threshold.global=80
# 4. 依存脆弱性スキャン
- run: pnpm audit --audit-level=moderate
# 5. E2E (Playwright — 主要ユーザーフローのみ)
- run: pnpm playwright test --reporter=line
# 6. ビルド成功確認
- run: pnpm build
このうち 1つでも red になったら merge できない。これにより、人間レビュアは「設計の妥当性」だけを見ればよくなります。
- 100% 譲渡の成立条件 — 自社固有ライブラリを作らない
クライアントのリポジトリに 自社専用ライブラリへの依存
を残すと、譲渡の意味がなくなります。「コードを渡したけど動かすには毎月ライセンス料が要る」は譲渡ではありません。
譲渡可能なスタック選定の基準
┌────────────────┬────────────────────────────────┬────────────────────────────────────────────────────┐
│ カテゴリ │ ✅ 選ぶ │ ❌ 避ける │
├────────────────┼────────────────────────────────┼────────────────────────────────────────────────────┤
│ フレームワーク │ Next.js / Remix / Hono │ 自社製フレームワーク │
├────────────────┼────────────────────────────────┼────────────────────────────────────────────────────┤
│ ORM │ Drizzle / Prisma │ 自社製ORM │
├────────────────┼────────────────────────────────┼────────────────────────────────────────────────────┤
│ 認証 │ NextAuth / Lucia / Better Auth │ 自社製認証SDK │
├────────────────┼────────────────────────────────┼────────────────────────────────────────────────────┤
│ デプロイ │ Vercel / Fly / Railway │ 自社製プラットフォーム │
├────────────────┼────────────────────────────────┼────────────────────────────────────────────────────┤
│ UI │ shadcn/ui / Tailwind │ 自社製コンポーネントライブラリ(クローズドソース) │
└────────────────┴────────────────────────────────┴────────────────────────────────────────────────────┘
譲渡後、クライアントが どの開発会社・どのエンジニアでも保守できる ことが、100% の本質です。
- MVPではない の成立条件 — Day 12 を専用QAデーにする
Day 0〜11 で機能を全部作っても、Day 12 を 「機能追加禁止 / QAだけ」 に固定しないと「動くMVP」止まりになります。
Day 12 QA チェックリスト(抜粋)
- モバイル: 360px / 768px / 1024px / 1440px の全幅で全画面確認
- フォーム: バリデーション境界値(空、最大長、不正値)
- 認証: トークン期限切れ後のリダイレクト
- 決済: 失敗パターン(カード拒否、3DS、Webhook 二重送信)
- エラー: 404 / 500 / ネットワーク切断時の画面
- パフォーマンス: Lighthouse 90 以上、TTI < 2.5s
- アクセシビリティ: axe で violations: 0
- セキュリティ: OWASP Top 10 簡易チェック
このうち1つでも red の状態で Day 14 納品はしません。「MVPだから後で直す」は許容しない が 14 日納品 ×
本番品質を成立させる最後のピースです。
まとめ
「初回無料」「14日納品」「コード100%譲渡」をマーケティング上のスローガンとして掲げる会社はいくつかあります。ただし
3つを同時に成立させようとすると、技術スタックと開発フローの両方を再設計する必要 があります。
┌──────┬────────────────────────────────┐
│ 数字 │ コード上の制約 │
├──────┼────────────────────────────────┤
│ $0 │ 営業工程を自動化する │
├──────┼────────────────────────────────┤
│ 14日 │ Day 0 でスキーマ完成、CI厳格化 │
├──────┼────────────────────────────────┤
│ 100% │ 自社固有依存を作らない │
└──────┴────────────────────────────────┘
この3つを成立させる開発チームの実装例として、私たちは Fluxez というプロジェクトを運営しています。GitHub
にコード例とテンプレートを公開しているので、興味があれば見てみてください。
