栽培管理アプリを作ってます③:農業アプリの設計がだいたいできた話

前回の記事では、Supabase SSRへの移行について書きましたが、今回は栽培管理アプリの設計に着手しました。

ClaudeとChatGPTとを使って壁打ちしながら設計を整理していったら、かなりクリアになってきました。

※個人的にはClaudeのほうが好きなんですが、使用制限の改悪(週間制限が導入)のため、ChatGPT→Claudeの順で検討しました。

目次

最初に作った構図

まず、最初に作ったアプリ構成はこんな感じでした。

ページ構成

  • /fields:圃場(ハウス)の一覧・新規登録
  • /plantings:作付の一覧・新規登録
  • /logs:作業ログの一覧・新規登録
  • /setup:畝の自動生成
  • /bed-canvas:3Dでハウスを表示

一見すると、それぞれ役割があるようには見えます。

テーブル構造

データベースも一通り揃っていました。

cult_fields    -- 圃場
cult_beds      -- 畝
cult_plantings -- 作付
cult_logs      -- 作業ログ

リレーションもちゃんと組んであって、RLSも設定済み。技術的には問題なさそうです。

3D表示

React Three Fiberを使って、ハウスを3Dで表示する機能も実装していました。

黒背景に緑のワイヤーフレームで、くるくる回せるやつです。

ハウスの中の畝をクリックすることで管理しようとしていました。

何が「しっくりこない」のか

実際に農作業で使うことをイメージしたときに、いくつか疑問が湧いてきました。

ページがバラバラすぎる

圃場を登録して、作付を登録して、ログを記録する…という流れが、3つのページに分かれています。

実際の作業は「今日、この畝に灌水した」っていうシンプルなものなのに、なぜこんなに画面遷移が必要なんだろう?

3D表示の意味

くるくる回せるのは楽しいけど、圃場でスマホ片手に作業記録するときに、3D表示を回す必要ってあるのかな?

むしろタップしづらくないか?

作付(plantings)って必要?

よく考えたら、作付って「ハウスで今何を育てているか」という情報ですよね。

それ、別テーブルにする必要ある?ハウス情報に含めちゃダメなの?

こういう違和感を言語化したくて、Claudeに壁打ちをお願いしました。

設計の方向性が見えてきた

壁打ちを重ねていくうちに、いくつかの方向性が固まってきました。

モバイルファーストで記録に特化

このアプリは、圃場で使うものを想定しています。

つまり、モバイル前提。PC版は後で作業履歴を確認するときに使う程度。

だったら、モバイルでの使いやすさを最優先にすべきですよね。

  • タップ領域は大きく(最低44px×44px)
  • 文字入力は最小限に
  • 日付は今日がデフォルト
  • 作業種類はアイコンで選択

こういう基本的なことを、最初から考えるべきでした。

2D表示で温かみのあるデザイン

3Dをやめて2D表示に変更することにしました。

  • 背景は薄い土色や空色
  • ハウスは柔らかい緑や自然な茶色
  • アイコンはイラスト風

実用性も上がるし、見た目も良くなるかなと。

作業フローに沿ったUI

データベースの構造(fields、plantings、logs)ではなく、実際の作業の流れに沿ったUIにすることにしました。

  1. ログイン後、すぐに自分のハウスが2Dで表示される
  2. 畝をタップ
  3. アイコン(灌水・施肥・防除など)が出る
  4. タップして記録

これだけ。シンプル。

主要な設計ポイント

ここからは、具体的な設計のポイントを紹介します。

作物によって開始時期と終了時期が違う

例えば、アスパラガスは1月から10月が栽培期間です。トマトは別の時期だし、作物によって全然違う。

最初は「年度」という概念で管理しようと思ったんですが、年をまたぐ作物もあるし、そもそも「2025年度」なのか「2026年度」なのか曖昧になります。

そこで、作物開始・終了ボタンで明確に管理することにしました。

ハウス編集画面:
- 「作物を開始」ボタン → 作物名を入力、開始日が自動で今日に
- 「作物を終了」ボタン → 終了日が自動で今日に
- 「栽培再開」ボタン → 同じ作物をもう一度始める

これなら、年またぎでも問題なし。

履歴も「2025/01/15 〜 2025/10/31 アスパラガス」みたいに明確に残ります。

防除回数管理

農薬には使用回数の上限があります。

例えば「この農薬は1作で5回まで」みたいなルールがあって、それを超えると違反になる。

しかも、リセットのタイミングが作物や農薬によって違うんです。

  • 1作でリセット:作物が終了したらカウント0に戻る
  • 刈り取りごとにリセット:収穫のたびにカウント0に戻る(ニラとか)

この「刈り取りごと」が特に面倒で、手動で「回数リセット」ボタンを押す必要があります。

そこで、農薬管理ページを新設することにしました。

【農薬管理】

第1ハウス - アスパラガス

農薬X(殺虫剤)
├ 使用上限:5回 / 1作
├ 現在:3回使用
├ リセット条件:1作でリセット
└ 履歴:
   2025/01/15 - 1回目
   2025/02/22 - 2回目
   2025/03/30 - 3回目

[回数リセット]

これなら、うっかり上限を超えることもなくなります。

あと、防除記録では希釈計算も自動化します。

散布量(希釈後):100L
希釈倍率:1000倍
→ 使用量(原液):0.1L ← 自動計算

計算式は 散布量 ÷ 希釈倍率 です。

毎回計算するのは面倒なので、これは絶対に自動化したい。

モバイルファーストUI:2つのパターンを試す

畝をタップしたときに、どうやって作業アイコンを表示するか。

これは実際に触ってみないとわからないので、2パターン作って比較することにしました。

パターンA:フッター固定

画面下部に常にアイコンを表示。畝を選ぶと、そのアイコンで記録できる。

┌─────────────────┐
│  第1ハウス     │
│  アスパラガス     │
├─────────────────┤
│ [畝1] [畝2]      │ ← 畝2を選択中
│ [畝3] [畝4]      │
└─────────────────┘
├─────────────────┤
│ 灌水 施肥 防除 │ ← フッター固定
└─────────────────┘

メリット:親指で押しやすい、画面を覆わない

パターンB:サイドパネル

畝をタップすると、下から半分スライドしてアイコンが出てくる。

┌─────────────────┐
│  第1ハウス     │
│  アスパラガス     │
├─────────────────┤
│ [畝1] [畝2]      │
│ [畝3] [畝4]      │
├─────────────────┤ ← 下から半分スライド
│ 畝2 - 第1ハウス  │
│ 灌水          │
│ 施肥          │
│ 防除         │
└─────────────────┘

メリット:何を選んでいるか明確、よくあるUI

どっちが使いやすいかは、実際に作って触ってみて判断します。

テーブル設計の変更

設計が固まったので、テーブル構造も見直しました。

plantingsテーブルは削除

作物情報はcult_fields(ハウス)に統合します。

ALTER TABLE cult_fields
ADD COLUMN current_crop_name text,
ADD COLUMN current_crop_started_at timestamptz,
ADD COLUMN current_crop_ended_at timestamptz;

これで、「今何を育てているか」が一目瞭然。

作業マスタを追加

施肥・防除の詳細を管理するテーブルを追加します。

-- 作業種類マスタ
CREATE TABLE work_types (
  id bigserial primary key,
  owner_id uuid not null,
  category text not null,        -- 'fertilizer', 'pesticide', 'other'
  name text not null,             -- 作業名・資材名
  icon text,                      -- アイコン名
  dilution_ratio int              -- 希釈倍率(農薬のみ)
);

-- 作物別作業設定
CREATE TABLE crop_work_settings (
  id bigserial primary key,
  owner_id uuid not null,
  crop_name text not null,
  work_type_id bigint references work_types(id)
);

これで、作物ごとに使う作業を選択できるようになります。

例えば、アスパラガスなら「灌水、施肥、防除、株分け、収穫」、トマトなら「灌水、施肥、防除、誘引、摘芯、収穫」みたいに。

農薬管理テーブルを追加

防除回数を管理するテーブルも追加します。

CREATE TABLE pesticide_usage (
  id bigserial primary key,
  owner_id uuid not null,
  field_id bigint references cult_fields(id),
  work_type_id bigint references work_types(id),
  usage_limit int,                -- 使用上限回数
  reset_condition text,           -- 'per_crop', 'per_year', 'per_harvest'
  current_count int default 0     -- 現在の使用回数
);

これで、農薬の使用状況を一元管理できます。

作業ログに詳細項目を追加

ALTER TABLE cult_logs
ADD COLUMN work_type_id bigint references work_types(id),
ADD COLUMN amount numeric,           -- 使用量(kg, ℓ)
ADD COLUMN diluted_amount numeric,   -- 散布量(希釈後)
ADD COLUMN photo_url text,           -- 写真URL
ADD COLUMN work_minutes int,         -- 作業時間(分)
ADD COLUMN memo text;                -- メモ

これで、詳細な記録ができるようになります。

今後の実装予定

設計が固まったので、次は実装フェーズに入ります。

フェーズ1:基本機能(MVP)

まずは最低限動くものを作ります。

  • 認証機能(既存を流用)
  • ハウス新規登録(単棟のみ)
  • メイン画面(2Dハウス表示)- パターンA・B両方
  • 作業記録(灌水・施肥のみ、シンプル版)
  • 作業履歴一覧

目標: モバイルで基本的な記録ができる状態

フェーズ2:防除管理・詳細機能

次に、防除管理などの複雑な機能を追加します。

  • 作業マスタ機能
  • 防除記録(希釈計算、回数管理)
  • 農薬管理ページ
  • 写真添付機能
  • 連棟対応

目標: 本格的な栽培管理ができる状態

フェーズ3:分析連携・最適化

最後に、出荷アプリや分析アプリとの連携を実現します。

  • 出荷アプリとのデータ連携確認
  • 分析アプリへのデータ提供準備
  • PC版の最適化
  • パフォーマンス改善

目標: 3アプリ連携の実現

まとめ

今回は、栽培管理アプリの設計がだいたい固まりました。

特に、防除回数管理みたいな農業特有の複雑さは、生成AIだけだと見落としがちです。

現場目線で考えながら、作っていきたいと思います。


目次