https://emotional-critter-haven.lovable.app

🐄 Moomo 沐哞 — 把碎念交給你的小怪獸

一個私密情緒樹洞:把今天的不爽餵給你的小怪獸,看著牠變化、收集配件、完成治癒任務。

Moomo Banner

核心功能

功能說明
情緒輸入輸入一段碎碎念,AI 會溫柔接住你的情緒
AI 情緒分析基於 Gemini 2.5 Flash,辨識情緒類別、強度、具象關鍵字
怪獸外觀變化根據情緒結果組合身體顏色、表情、頭飾、手持物、背景
配件收集每次情緒輸入自動獲得與情緒相關的配件
治癒任務根據負面能量自動分配療癒小任務(附完成反思)
情緒日記封存小哞時保存完整的情緒統計、圖表與 AI 小結
匿名社群匿名分享怪獸外觀,留言互相鼓勵(附檢舉與安全機制)
圖鑑系統收集所有解鎖過的怪獸部件
危機求助AI 偵測危機內容時顯示固定求助卡片(1925、119、110、1980)
隱私控制刪除單筆紀錄、清空所有紀錄、刪除帳號資料

🏗️ 技術架構

Frontend              Backend / SSR           Database
┌─────────────┐      ┌──────────────┐       ┌─────────────┐
│ React 19    │      │ TanStack     │       │ Supabase    │
│ TanStack    │─────▶│ Start (SSR)  │──────▶│ PostgreSQL  │
│ Router      │      │ Server Fns   │       │ + RLS       │
│ React Query │      │              │       │ + Auth      │
│ Recharts    │      │ Vite 7       │       └─────────────┘
│ Tailwind 4  │      │ Cloudflare   │              │
└─────────────┘      │ Workers      │       ┌──────┴──────┐
                     └──────────────┘       │ Gemini 2.5  │
                                            │ Flash (AI)  │
                                            └─────────────┘
技術用途
React 19UI 框架
TanStack StartSSR + Server Functions
TanStack Router檔案式路由
TanStack React Query資料同步與快取
Vite 7開發伺服器與打包
Tailwind CSS 4樣式系統
SupabasePostgreSQL + Auth + RLS
Cloudflare Workers部署目標
Recharts情緒統計圖表
ZodAI 回傳格式驗證
SonnerToast 通知
Lucide React圖示

📊 資料表設計

erDiagram
    auth_users ||--o{ profiles : "1:1"
    auth_users ||--o{ monsters : "owns"
    auth_users ||--o{ emotion_entries : "writes"
    auth_users ||--o{ accessories : "collects"
    auth_users ||--o{ user_tasks : "assigned"
    auth_users ||--o{ diaries : "archives"
    auth_users ||--o{ community_posts : "shares"
    auth_users ||--o{ post_comments : "writes"
    auth_users ||--o{ post_likes : "likes"
    auth_users ||--o{ post_reports : "reports"

    monsters ||--o{ emotion_entries : "receives"
    monsters ||--o{ accessories : "wears"
    monsters ||--o{ user_tasks : "has"
    monsters ||--o{ diaries : "archived_as"
    monsters ||--o{ community_posts : "shown_in"

    healing_tasks ||--o{ user_tasks : "template"
    community_posts ||--o{ post_comments : "has"
    community_posts ||--o{ post_likes : "has"
    community_posts ||--o{ post_reports : "flagged_by"
    post_comments ||--o{ post_reports : "flagged_by"

    profiles {
        uuid id PK
        text display_name
        text anonymous_name
    }

    monsters {
        uuid id PK
        uuid user_id FK
        text name
        text status
        int mood_score
        int negative_energy
        int positive_energy
        jsonb appearance
    }

    emotion_entries {
        uuid id PK
        uuid user_id FK
        uuid monster_id FK
        text raw_text
        text primary_emotion
        int emotion_intensity
        text llm_reply
        jsonb analysis
    }

    accessories {
        uuid id PK
        uuid user_id FK
        uuid monster_id FK
        text slot
        text name
        boolean equipped
    }

    healing_tasks {
        uuid id PK
        text title
        text description
        int reward_value
    }

    user_tasks {
        uuid id PK
        uuid user_id FK
        uuid monster_id FK
        uuid task_id FK
        text status
        text reflection
    }

    diaries {
        uuid id PK
        uuid user_id FK
        uuid monster_id FK
        date start_date
        date end_date
        jsonb emotion_summary
        jsonb appearance
    }

    community_posts {
        uuid id PK
        uuid user_id FK
        uuid monster_id FK
        text anonymous_name
        text caption
        text status
        int like_count
        int comment_count
        jsonb appearance
    }

    post_comments {
        uuid id PK
        uuid post_id FK
        uuid user_id FK
        text content
    }

    post_likes {
        uuid post_id PK
        uuid user_id PK
    }

    post_reports {
        uuid id PK
        uuid post_id FK
        uuid comment_id FK
        uuid reporter_id FK
        text reason
        text status
    }

    sprite_parts {
        uuid id PK
        text layer
        text key
        text name
        text rarity
        text[] emotion_tags
    }

🚀 安裝方式

前置需求

步驟

# 1. Clone 專案
git clone https://github.com/Dannygod/emotional-critter-haven.git
cd emotional-critter-haven

# 2. 建立環境變數
cp .env.example .env
# 然後填入你的 Supabase 連線資訊

# 3. 安裝依賴
bun install
# 或 npm install

# 4. 套用資料庫 Migration
# 方法 A: Supabase CLI
supabase db push

# 方法 B: 手動到 Supabase Dashboard > SQL Editor 依序執行 supabase/migrations/*.sql

# 5. 啟動開發伺服器
bun run dev
# 或 npm run dev

🔑 環境變數說明

變數名稱用途來源
SUPABASE_URLSupabase API URL (SSR)Supabase Dashboard > Settings > API
SUPABASE_PUBLISHABLE_KEYSupabase anon key (SSR)同上
VITE_SUPABASE_URLSupabase API URL (Client)同上
VITE_SUPABASE_PUBLISHABLE_KEYSupabase anon key (Client)同上
VITE_SUPABASE_PROJECT_IDSupabase project IDSupabase Dashboard > Settings > General

注意VITE_ 前綴的變數會被 Vite 注入到前端 bundle 中。SUPABASE_PUBLISHABLE_KEY 是 anon key,本身權限受 RLS 限制,可安全暴露給前端。

📁 專案目錄結構

emotional-critter-haven/
├── src/
│   ├── components/         # UI 元件
│   │   ├── MonsterSprite.tsx    # 怪獸組合渲染
│   │   ├── CrisisCard.tsx       # 危機求助卡片
│   │   └── ui/                  # shadcn/ui 基礎元件
│   ├── lib/
│   │   ├── emotion/             # 情緒分析模組(拆分後)
│   │   │   ├── ai-analyze.ts        # AI 呼叫與 prompt
│   │   │   ├── ai-schema.ts         # Zod 驗證 schema
│   │   │   ├── appearance-picker.ts # 怪獸外觀組合
│   │   │   ├── mood-calculator.ts   # 情緒分數計算
│   │   │   ├── task-assigner.ts     # 治癒任務分配
│   │   │   ├── safety.ts           # 安全等級常數
│   │   │   └── index.ts            # Server functions 入口
│   │   ├── privacy.functions.ts # 隱私控制 server functions
│   │   ├── auth.tsx             # 認證 context
│   │   └── utils.ts
│   ├── integrations/supabase/   # Supabase 客戶端與型別
│   ├── routes/
│   │   ├── _authenticated/
│   │   │   ├── home.tsx         # 主頁(情緒輸入 + 怪獸)
│   │   │   ├── tasks.tsx        # 治癒任務(附反思)
│   │   │   ├── diary.tsx        # 情緒日記(附圖表)
│   │   │   ├── gallery.tsx      # 部件圖鑑
│   │   │   ├── community.tsx    # 匿名社群(附檢舉)
│   │   │   └── settings.tsx     # 設定(附隱私控制)
│   │   └── ...
│   └── styles.css
├── supabase/
│   └── migrations/              # 資料庫 Migration 檔案
├── .env.example                 # 環境變數範本
├── package.json
├── vite.config.ts
└── README.md

🔒 安全與隱私

Row Level Security (RLS)

所有資料表都啟用了 Supabase RLS:

  • 個人資料(monsters, emotion_entries, accessories, user_tasks, diaries):僅限擁有者讀寫
  • 社群貼文:所有已登入使用者可讀取 status = 'published' 的貼文
  • 怪獸外觀:僅擁有者或被公開貼文引用時才可讀取
  • 檢舉紀錄:僅檢舉者本人可讀取自己的檢舉

隱私控制

使用者可以在「設定」頁面進行以下操作:

  • 刪除單筆情緒紀錄
  • 清空所有情緒紀錄
  • 刪除全部帳號資料
  • 查看完整隱私說明