業者向けオンボーディング Vendor onboarding
Flutter モバイルアプリ開発を新規に担当する外部業者が、初日に読み終え、2 日目から開発に着手する
ことを目的にしたエントリーガイドです。本ページは mobileapp/CLAUDE.md の HTML 版で、
プロジェクト全体の規約と接面ルールを最短ルートでつかむための章立てになっています。
An entry guide for external Flutter vendors joining the project. Goal: read it on day 1, start coding on day 2.
This page mirrors mobileapp/CLAUDE.md in HTML, structured to give the fastest possible path
to the project's conventions and integration surface.
1. Day-1 Reading Order 1. Day-1 reading order
以下を上から順に 5〜10 分で読み流してください。各項目は別ドキュメントへのジャンプ台です。
Skim the following in order — about 5 to 10 minutes total. Each item is a jump-off point to a deeper doc.
- 本ページ §2 アーキテクチャ概要 — Flutter ↔ BFF の責任分界
- This page §2 Architecture overview — Flutter / BFF responsibilities
- 本ページ §3 ViewEnvelope の読み方 — BFF が返す共通 JSON 構造
- This page §3 How to read a ViewEnvelope — the shared response shape
- 本ページ §4 画面追加フロー(7 ステップ) — 仕事の進め方
- This page §4 Adding a screen (7 steps) — the operational flow
- 本ページ §5 コーディング規約と §6 やってはいけないこと
- This page §5 Coding conventions and §6 What not to do
- prototype/flutter/README.md — 起動手順 (
scripts/run.sh) - prototype/flutter/README.md — How to run the app (
scripts/run.sh) - architecture.html — 接続先と責任分界
- architecture.html — Connection surface & responsibility split
- view-envelope-guide.html — SDUI L3 と envelope 仕様
- view-envelope-guide.html — SDUI L3 and envelope spec
- redoc.html —
/v1/mobile/*の OpenAPI - redoc.html — OpenAPI for
/v1/mobile/*
2. アーキテクチャ概要 2. Architecture overview
2.1 関係図 2.1 Component relationships
flowchart LR subgraph Flutter["Flutter App
mobileapp/prototype/flutter/"] direction TB UI[Screens / Widgets] Core[core/bff
ViewEnvelope receiver] Auth[supabase_flutter
Auth only] Gen[generated/parky_api
dio client] end subgraph BFF["Cloudflare Workers BFF
api/src/bff/mobile/"] Views[/v1/mobile/views/home-feed 等
ViewEnvelope/] Actions[/v1/mobile/actions/sessions/start 等
ActionEnvelope/] Tele[/v1/mobile/telemetry/events
TelemetryAck/] end PG[(Supabase Postgres
+ RLS)] R2[(Cloudflare R2
images)] Ext[Mapbox / FCM /
Stripe / Resend] SAuth[Supabase Auth] UI --> Core Core --> Gen Gen -.HTTPS + JWT.-> Views Gen -.HTTPS + JWT.-> Actions Gen -.HTTPS + JWT.-> Tele Auth -.JWT only.-> SAuth Views --> PG Actions --> PG Views --> R2 Actions --> Ext
2.2 接続先の原則 2.2 Connection rules
Flutter からアクセスして良い外部サーフェスは 2 つだけ です。
The Flutter client may only talk to two external surfaces.
| 接続先Surface | 用途Purpose | SDKSDK |
|---|---|---|
Cloudflare Workers BFFhttps://dev-api.parky.co.jp/v1/mobile/* |
画面取得・操作・テレメトリ。全データ・全ビジネス判定はここ経由Fetch screens, run actions, push telemetry. All data and business decisions flow through here | dio + 生成 Dart クライアントdio + generated Dart client |
| Supabase Auth | サインイン / OTP / JWT 取得・更新 / パスワード変更 / 退会Sign-in / OTP / JWT acquisition & refresh / password change / account deletion | supabase_flutter の Auth 機能のみAuth features only |
- Supabase DB の
from()/rpc()直叩き - Direct Supabase DB
from()/rpc() - Supabase Edge Functions の直接呼び出し
- Direct calls to Supabase Edge Functions
- Supabase Storage への直 PUT(R2 upload は BFF 発行 presigned URL 経由)
- Direct Supabase Storage PUTs (R2 uploads must use a BFF-issued presigned URL)
- Supabase Realtime 購読
- Supabase Realtime subscriptions
2.3 BFF の 3 種 endpoint 2.3 The three BFF endpoint kinds
| 種別Kind | パスPath | 戻りReturns | 用途Purpose |
|---|---|---|---|
| View | views (例: /v1/mobile/views/home-feed) |
ViewEnvelope |
1 画面分のデータ取得(read)Fetch one screen worth of data (read) |
| Action | actions (例: /v1/mobile/actions/sessions/start) |
ActionEnvelope |
ユーザー操作(write)。次画面の data を同梱User operation (write). Carries the next screen's data |
| Telemetry | /v1/mobile/telemetry/events |
TelemetryAck |
fire-and-forget なログ送信Fire-and-forget log delivery |
3. ViewEnvelope の読み方(SDUI L3) 3. How to read a ViewEnvelope (SDUI L3)
Parky は Server-Driven UI Level 3 固定。サーバーは「data + UI を駆動するメタ情報」を返し、 Flutter は決まった方針でレンダリングします。L4 / L5 のような UI コンポーネントツリー(JSX 相当)は返しません。
Parky uses Server-Driven UI Level 3. The server returns data plus UI-driving metadata. Flutter renders following a fixed contract. The server does not return UI component trees (no L4 / L5).
3.1 envelope の構造(早見表) 3.1 Envelope shape (cheat sheet)
| キーKey | 役割Role | Flutter 側の典型処理Flutter handling |
|---|---|---|
data |
画面固有のドメインデータScreen-specific domain data | DTO に decode → ViewModel に渡すDecode into DTO, hand to ViewModel |
ui_config |
A/B / experiment_id / theme_hint / highlighted_fieldsA/B, experiment_id, theme_hint, highlighted_fields | feature flag / experiment 送信に流用Wire to feature flags & experiment telemetry |
navigation |
遷移指示。target / params / strategyNavigation directive (target/params/strategy) |
NavigationResolver がルーターに渡すNavigationResolver feeds the router |
validation |
フォーム field rule の事前列挙Up-front list of form field rules | ローカル先行チェック、message_code を i18n 解決Run validations locally, resolve message_code via i18n |
states.skeleton |
loading 中の skeleton レイアウト hintSkeleton layout hint while loading | shimmer の枠を決めるDrive the shimmer frame |
states.empty |
0 件時の empty view 指示Empty-state directive when zero results | title_code/body_code/cta で widget を組むCompose widget from title_code/body_code/cta |
states.error[] |
この endpoint で起こり得る error の事前列挙Up-front list of errors this endpoint can emit | code → fallback / retry / message を決定Pick fallback / retry / message based on code |
fallback_behavior |
通信不達 / auth 失効 / version mismatch 時の規約Contract for network / auth / version-mismatch failures | on_network_error 等を読んで挙動分岐Branch on on_network_error etc. |
meta.server_time |
サーバー時刻(時刻ズレ警告)Server clock (used for clock-skew warnings) | client 時刻と diff 算出Diff against client clock |
meta.cache_key |
composite ETag。client cache の invalidate 用Composite ETag for cache invalidation | 次 request の If-None-Match に使うSend back as If-None-Match |
meta.min_app_version |
この endpoint が要求する最小 client versionMinimum client version this endpoint requires | semver 比較 → degraded / force_updateCompare semver → degraded / force_update |
meta.expected_ui_version |
サーバー側 ui_layer catalog の版数Server-side ui_layer catalog version | cache とズレていれば background /boot 再 fetchIf cache differs, refetch /boot in background |
meta.view_spec_ref |
/boot の ui_layer.view_specs[id] への参照 keyReference key into ui_layer.view_specs from /boot |
spec 本体を cache から resolveResolve spec body from cache |
詳細・JSON 例はFull details & JSON examples in view-envelope-guide.html を参照。.
4. 画面追加フロー(7 ステップ) 4. Adding a screen (7 steps)
新規画面の追加、または既存画面の data 形変更は、必ず以下の順序で進めてください。 どこかを飛ばすと CI で落ちます。
Add a new screen — or change an existing screen's data shape — by going through the steps below in order. Skipping any step will trip CI.
| # | ステップStep | 場所 / コマンドLocation / command |
|---|---|---|
| 1 | View Model schema 定義Define the View Model schema | api/src/schema/view/<view-name>-view.ts (Zod) |
| 2 | BFF view 実装Implement the BFF view | api/src/bff/mobile/views/<name>.ts + buildViewEnvelope({...}) |
| 3 | OpenAPI 生成Regenerate OpenAPI | curl http://127.0.0.1:8787/v1/openapi.json > docs/openapi.json |
| 4 | Flutter 側 codegenRun Flutter codegen | bash scripts/regen_api.sh (in prototype/flutter/) |
| 5 | Widget 実装Implement widgets | prototype/flutter/lib/features/<feature>/{data,application,presentation}/ |
| 6 | Golden testAdd golden tests | prototype/flutter/test/golden/ (flutter test --update-goldens) |
| 7 | SubmitSubmit | dev ブランチ直 push、API/Flutter は同一 PRPush directly to dev; bundle API + Flutter changes in one PR |
5. Flutter 側コーディング規約 5. Flutter coding conventions
5.1 ディレクトリ構成 5.1 Directory layout
| ディレクトリDirectory | 役割Role |
|---|---|
lib/app.dart / app_router.dart |
アプリ entrypoint・GoRouter 設定App entrypoint & GoRouter setup |
lib/config/ |
環境設定(mapbox / supabase / sentry / parky_api)Environment config (mapbox / supabase / sentry / parky_api) |
lib/core/ |
横断レイヤー(auth / bff / codes / i18n / sdui / theme / widgets …)Cross-cutting layer (auth / bff / codes / i18n / sdui / theme / widgets …) |
lib/features/<feature>/ |
data/ + application/ + presentation/ の 3 段Three sub-folders: data/, application/, presentation/ |
lib/generated/parky_api/ |
OpenAPI から生成された Dart クライアント(編集禁止)Generated Dart client from OpenAPI (do not edit) |
5.2 命名・状態管理・テスト 5.2 Naming, state, testing
- ファイル:
snake_case.dart/ クラス:UpperCamelCase/ 変数:lowerCamelCase - Files:
snake_case.dart/ classes:UpperCamelCase/ variables:lowerCamelCase - DTO は freezed + json_serializable(
<feature>_dto.dart+.freezed.dart+.g.dart) - DTOs use freezed + json_serializable (
<feature>_dto.dart+.freezed.dart+.g.dart) - 状態管理は Riverpod 一本。controller は AsyncNotifier、表示は
AsyncValueWidget/async_scaffold - State management is Riverpod only. Controllers are AsyncNotifiers; rendering uses
AsyncValueWidget/async_scaffold - テスト: unit / widget は
test/、golden はtest/golden/、integration はintegration_test/ - Tests: unit and widget under
test/, goldens undertest/golden/, integration underintegration_test/ - BFF 呼び出しは必ず生成型 +
ParkyBffClient経由(素の dio 直叩き禁止) - BFF calls always go through the generated client +
ParkyBffClient(no raw dio)
6. やってはいけないこと(落とし穴) 6. What not to do (pitfalls)
- envelope の構造を Flutter 側で勝手に変える(
ui_config無視 /navigation.target無視) - Mutating the envelope shape on the Flutter side (ignoring
ui_configornavigation.target) - BFF にない API を Flutter 側だけで増やす — 必ず BFF に endpoint を追加
- Adding APIs only on the Flutter side — always add the BFF endpoint first
- Supabase DB / RPC / Edge Functions / Storage / Realtime を直叩き
- Calling Supabase DB / RPC / Edge Functions / Storage / Realtime directly
states.errorを無視して全エラーを 1 つの toast で済ます- Ignoring
states.errorand lumping all errors into one toast
6.1 認証 token の扱い 6.1 Auth token handling
- Supabase JWT は
flutter_secure_storage経由のみ(OS Keychain / Keystore) - Supabase JWT only via
flutter_secure_storage(OS Keychain / Keystore) - BFF への送信は
Authorization: Bearer <JWT>(ParkyBffClientの interceptor が自動付与) - Send to BFF with
Authorization: Bearer <JWT>(handled automatically byParkyBffClient) - JWT を SharedPreferences / 平文ファイル / ログに書かない、BFF 以外のドメインに送らない
- Never write JWTs to SharedPreferences, plaintext files, or logs; never send to non-BFF domains
- Supabase service_role key / Mapbox secret token / Stripe secret 等を Flutter binary に同梱しない
- Never bundle Supabase service_role key, Mapbox secret token, or Stripe secret in the Flutter binary
6.2 envelope の必須フィールド欠落 6.2 Missing required envelope fields
meta.min_app_versionを null や "0.0.0" にして version mismatch を骨抜きにしない- Don't blank out
meta.min_app_version(or set "0.0.0") just to skip the version-mismatch check fallback_behaviorを未指定で envelope を組まない(buildViewEnvelopeの必須引数)- Don't build an envelope without
fallback_behavior(it's a required arg ofbuildViewEnvelope) states.errorに該当 endpoint で起こり得る code を必ず網羅- Cover every error code the endpoint can emit in
states.error
6.3 codegen / lockfile を手で触らない 6.3 Don't hand-edit codegen / lockfiles
lib/generated/parky_api/配下はscripts/regen_api.shでのみ更新- Update
lib/generated/parky_api/only viascripts/regen_api.sh pubspec.lockを手書き編集しない- Never hand-edit
pubspec.lock infra/supabase/baseline/も生成物なので手書き禁止- Same applies to
infra/supabase/baseline/— it's generated
7. 質問先・コミュニケーション 7. Communication channels
| 用途Purpose | 宛先Where |
|---|---|
| 仕様確認・実装相談・PR レビュー依頼Spec questions / implementation help / PR review | dev@parky.co.jp |
| 緊急(本番障害・セキュリティ)Emergency (prod incident / security) | dev@parky.co.jp に "[P0]" prefixdev@parky.co.jp with a "[P0]" subject prefix |
Slack / Discord は業者向けには現時点で開放していません。連絡は email + GitHub PR コメントが主要チャネルです。
Slack and Discord are not currently exposed to vendors. Email and GitHub PR comments are the main channels.
7.1 PR の作り方 7.1 How to open a PR
- ブランチは
devに直 push(Parky 全体ルール)。feature/*ブランチは作らない - Push directly to
dev(project-wide rule). Do not createfeature/*branches - API + Flutter 両方触る場合は同一 PR(OAS / docs / 生成物の整合性が必須)
- If you touch both API and Flutter, do it in a single PR (OAS / docs / codegen must stay aligned)
- PR description: 変更概要・スクショ or 動画・
flutter test/npm test結果 - PR description should include change summary, screenshots/videos, and
flutter test/npm testresults
8. 関連ドキュメント 8. Related documents
| ドキュメントDocument | 内容Content |
|---|---|
| mobileapp/CLAUDE.md | 本ページの md 版(mobileapp/ 配下作業時の SSoT)Markdown version of this page (SSoT when working under mobileapp/) |
| view-envelope-guide.html | SDUI L3 / ViewEnvelope の業者向け技術解説Vendor-oriented deep dive on SDUI L3 / ViewEnvelope |
| architecture.html | システム全体像・責任分界System architecture & responsibility split |
| redoc.html / api-spec.html | OpenAPI 表示(Redoc / Swagger UI)OpenAPI rendering (Redoc / Swagger UI) |
| pages.html / user-flows.html | 画面カタログ・E2E シナリオScreen catalog & E2E scenarios |
| auth-flows.html / onboarding.html | 認証フロー・初回起動オンボーディング画面仕様Authentication flow & first-launch onboarding screen spec |
| prototype/flutter/README.md | 起動手順・--dart-define-from-file・openapi codegenHow to run, --dart-define-from-file, OpenAPI codegen |
9. リリーススケジュール 9. Release schedule
- 2026-06-30: ストアリリース予定(iOS / Android 同時)
- 2026-06-30: planned store release (iOS & Android simultaneously)
- それまで: 後方互換不要。breaking change OK
- Until then: no backwards compat required; breaking changes are fine
- リリース後:
min_app_version/sunset_dateを活用した段階的廃止運用に移行 - After launch: shift to a staged deprecation flow using
min_app_versionandsunset_date