🤖
Next.js × Supabase で作る「家事やってますアピールアプリ」
Next.js × Supabase で作る「家事やってますアピールアプリ」
はじめに
家庭を持っている皆さん、こんな経験はありませんか?
「今日も家事やったのに、家族に気づいてもらえない...」
「パートナーがどのくらい家事をやっているのか分からない...」
そんな切実な悩みから生まれたのが、今回開発した「家事やってますアピールアプリ」です。
家族間で家事の実施状況を共有・可視化することで、お互いの頑張りを認め合えるようになります。
💡 なぜこのアプリを作ったのか
きっかけ
家事は目に見えない労働です。
- 毎日やるのが当たり前だと思われがち
- やって当然、やらないと怒られる
- 頑張りが認められにくい
こうした問題を解決するために、家事を可視化し、家族間で共有できるアプリケーションを開発しました。
解決したい課題
-
家事の不平等感の解消
- 誰がどのくらい家事をやっているか一目で分かる
-
コミュニケーションの改善
- 家事の実施状況を共有することで感謝の気持ちが生まれる
-
モチベーションの向上
- 自分の家事実績が記録されることで達成感を得られる
🏗️ アプリケーション概要
主な機能
-
ユーザー認証: メールアドレス・パスワードでのサインアップ・ログイン
-
タスク管理: 家事タスクの登録・編集・削除

-
進捗可視化: ダッシュボードでグラフィカルに表示

-
家族共有: グループ機能で家族メンバーのタスクを共有
技術スタック
- フロントエンド: Next.js 15 (App Router) + TypeScript
- バックエンド: Next.js API Routes
- データベース: Supabase (PostgreSQL)
- 認証: Supabase Auth + JWT
- スタイリング: Tailwind CSS
- 状態管理: React Context API
🔧 工夫したポイント
1. セキュリティ面の強化
Cookieベースのセッション管理
工夫点:
-
httpOnlyフラグでJavaScriptからのアクセスを防止 - 本番環境では
secureフラグでHTTPS必須 - アクセストークンとリフレッシュトークンの適切な有効期限設定
JWTトークンによる認証
工夫点:
- トークンの自動リフレッシュ機能
- 認証エラー時の適切なハンドリング
- サーバーサイドでの認証状態管理
Row Level Security (RLS) によるデータ保護
-- 全員に SELECT を許可
create policy "Allow select for authenticated users"
on tasks
for select
using (true);
-- INSERT は自分の user_id でのみ許可
create policy "Allow insert for authenticated users"
on tasks
for insert
with check (user_id = auth.uid());
-- UPDATE は自分のタスクのみ
create policy "Users can update their own tasks"
on tasks
for update
using (user_id = auth.uid());
-- DELETE も自分のタスクのみ
create policy "Users can delete their own tasks"
on tasks
for delete
using (user_id = auth.uid());
工夫点:
- データベースレベルでのアクセス制御
- ユーザーが自分のデータにのみアクセス可能
- SQLインジェクション攻撃に対する防御
2. レスポンシブデザインの実装
// フレキシブルなタスクカードレイアウト
<div className="bg-white p-4 rounded shadow flex-1 min-w-[200px]">
<h3 className="text-lg font-bold">{task.title}</h3>
<p>カテゴリ: {task.category}</p>
<p>日付: {task.date}</p>
<p>実施者: {task.userName}</p>
<div className="flex gap-2 mt-2">
<button className="bg-yellow-500 text-white px-2 py-1 rounded">
編集
</button>
<button className="bg-red-500 text-white px-2 py-1 rounded">
削除
</button>
</div>
</div>
工夫点:
- Tailwind CSSを活用したレスポンシブデザイン
- スマートフォンからデスクトップまで対応
- カードレイアウトの柔軟な表示
3. ドメイン駆動設計(DDD)の採用
レポジトリパターンの実装
// ドメイン層: インターフェース定義
export interface ITaskRepository {
findByUserIds(userIds: string[]): Promise<Task[]>;
create(userId: string, title: string, category: string, date: string): Promise<Task>;
update(taskId: number, title: string, category: string): Promise<Task>;
delete(taskId: number): Promise<void>;
}
// エンティティ定義
export class Task {
constructor(
public readonly taskId: number,
public title: string,
public category: string,
public date: string,
public userName: string,
) {}
static fromRecord(record: TaskRecord): Task {
const username = Array.isArray(record.users)
? (record.users[0]?.username ?? '')
: (record.users?.username ?? '');
return new Task(record.task_id, record.title, record.category, record.date, username);
}
}
ドメイン層・リポジトリの工夫点
- CRUD操作だけの単純なアプリなので、厳密なDDDを導入するメリットは少ないように感じた
- ただし、役割ごとにディレクトリを分けることで、コードの構造が整理され可読性が向上
- インターフェース
ITaskRepositoryを使ったことで、実装の差し替えやテスト用モックの導入が容易 - ドメインエンティティ
Taskを通してデータを扱うため、将来的にビジネスロジックを追加する際も変更箇所を集中させられる
微妙な点
- 今の段階ではドメイン層に複雑なビジネスロジックがないため、DDDの構造はややオーバーエンジニアリング気味
- 単純な CRUD だけなら、リポジトリなしで API 直呼び出しでも問題ない
4. ユーザビリティの向上
ローディング状態の管理
// Context APIによるグローバル状態管理
const { showLoading, hideLoading } = useLoading();
const login = async () => {
showLoading();
try {
const response = await signin({ email: email, password: password });
// ログイン成功処理
} catch (error) {
// エラーハンドリング
} finally {
hideLoading();
}
};
工夫点:
- 非同期処理中のユーザー体験向上
- グローバルなローディング状態管理
- 一貫したUI/UX
🎯 今後の改善予定
機能面
- 通知機能: タスク完了時のプッシュ通知
- ポイント制度: 家事実績に応じたポイント付与
- カテゴリ管理: カスタムカテゴリの追加・編集
技術面
- パフォーマンス最適化: React.memo、useMemo等の活用
- 単体テストコード作成: Jestの活用
- CI/CD: GitHub Actionsの活用
📝 まとめ
家事という日常的な作業を「見える化」することで、家族間のコミュニケーション改善を目指したアプリケーションを開発しました。
技術的な学び
- セキュリティファースト: 認証・認可の実装
- アーキテクチャ設計: DDDによる保守性の高いコード
- ユーザー体験: レスポンシブデザイン
開発を通じて得られた知見
- Supabaseの強力なRLS機能
- Next.js App Routerの柔軟性
家事という身近なテーマから始まったこのプロジェクトですが、モダンなWebアプリケーション開発のベストプラクティスを多く学ぶことができました。
Discussion