May 14, 2026
ð¹ïž OHO-MATE

ì ì¥ì: octxxiii/Oho-Mate
ð¹ïž OHO-MATE
íêµ ìë²ìì íµíë íêµìŽ â ê²ìŽëšž í¹í C2C ìžìŽ íìµ íë«íŒ Korean for Gamers. Real lessons. Real progress. Recorded forever.
ð ê°ì (Overview)
OHO-MATEë íêµ ê²ì ìë²ìì ì€ì ìíµì ìíë ìžêµìž íìµìì ê²ìŠë íêµìž íí°ë¥Œ ë§€ì¹íë C2C ìžìŽ íìµ íë«íŒì ëë€.
- ð® LoL, VALORANT, ë§ìží¬ëííž ê²ì 컚í ì€íž í¹í ìì
- ðïž ìžì± ìì± íµí â Agora RTC êž°ë°, íë«íŒ ìŽí ìì
- ð€ AI íìµ ëŠ¬í¬íž â GPT-4o-miniê° ê²ì ë§¥ëœ + 묞í ë žíž í¬íš ë¶ì
- ð¬ ì€ìê° ì±í â Supabase Realtime, ìžë¶ ì°ëœì² ê³µì ì°šëš
- â XP + ì€ížëŠ ìì€í â ë 벚ì , ë°°ì§, ì°ì íìµ ë³Žì
OHO-MATE is a Korean language tutoring marketplace purpose-built for gamers who want to communicate in Korean game servers. Every lesson is recorded as an AI report â êž°ë¡ëì§ ìë ê²ì ê³µë¶ê° ìëë€.
⚠죌ì êž°ë¥ (Features)
ð® íìµì (Learner)
| êž°ë¥ | ì€ëª |
|---|---|
| ð íí° íì | êŽì¬ì¬ íê·ž / ìŽëŠ ê²ì / íì ·ê°ê²©Â·ìì ì ì ë ¬ |
| ð ì°íêž° | ë§ìì ëë íí° ìì늬ì€íž ì ì¥ |
| ð íší€ì§ ììœ | ìì íší€ì§ ì í â Stripe ê²°ì â ìë ì±í 룞 ìì± |
| ðïž ìžì± ìì± ìì | /lesson/:id â Agora RTC ìì± + ë
žíž + ëšìŽ ì¹© |
| ð€ AI íìµ ëŠ¬í¬íž v2 | ê²ì íí · 묞í ë žíž Â· ë°ì í · ìŽí ë§ì€í°ëЬ % |
| ð íëì칎ë & íŽìŠ | 늬í¬ížìì ë°ë¡ íëì칎ë / 4ì§ì ë€ íŽìŠ ì í |
| ð¬ ì€ìê° ì±í | íí°ì ìžì± ë©ìì§ (ìžë¶ ì°ëœì² ê³µì ìë ê²œê³ ) |
| â XP & ë 벚 | ìì ìë£Â·ëŠ¬ë·°Â·ë¡ê·žìž ì€ížëŠìŒë¡ XP ì 늜, LV1~10 |
| ð ê²ì ëšìŽì¥ | LoL/VALORANT/ë§ìží¬ëííž/K-POP/K-Drama 84ê° íí |
| âïž ëŠ¬ë·° ìì± | ìì ìë£ í ë³ì + ìœë©íž (Supabase ì ì¥) |
| ð¹ïž ìšë³Žë© | ì ê· ê°ì í êŽì¬ì¬Â·ë 벚 ì í 2ëšê³ íë¡ì° |
ðšâð« íí° (Tutor)
| êž°ë¥ | ì€ëª |
|---|---|
| ð ì§ìì ì ì¶ | ApplyModal â ìŽëŠ, Discord, ìžìŽ, íê·ž, ìê° |
| ð ë±êž ìì€í | BRONZE / SILVER / GOLD ë°°ì§ |
| ð íí° ëì볎ë | ìì êŽëЬ, ìì íí©, ê²ì ëšìŽì¥ ê°ìŽë |
| ð° ì ì° ìì€í | ê³ ì KRW íìŽìì (íìš ì€ìê° ë°ì) |
ð¡ïž ìŽë믌 (Admin)
| êž°ë¥ | ì€ëª |
|---|---|
| ð ììµ ë¶ì | ìŽ ë§€ì¶, íë«íŒ ìŽìµ, íí° íìŽìì â ìë³ ì°šíž |
| â íí° ì¬ì¬ | ì§ìì 목ë¡, approve/reject ë²íŒ |
| ð€ AI 늬í¬íž í | ìì± ëêž° ì€ìž 늬í¬íž 몚ëí°ë§ |
ðïž ìí€í ì² (Architecture)
âââââââââââââââââââââââââââââââââââ
â React SPA (Vite) â
â src/pages src/components â
â src/context src/lib â
ââââââââââââââ¬âââââââââââââââââââââ
â
âââââââââââââââââââââââââŒââââââââââââââââââââââââ
â â â
âââââââââââŒâââââââââ ââââââââââââŒâââââââââââ ââââââââââŒâââââââââââ
â Supabase (BaaS) â â Stripe Payments â â Agora RTC â
â - Auth (JWT) â â - Checkout Session â â - Voice Lessons â
â - PostgreSQL â â - Webhook â lessons â â - Token: Edge Fn â
â - Realtime Chat â â - auto chat room â â - 50min timer â
â - Edge Functionsâ âââââââââââââââââââââââ âââââââââââââââââââââ
â · stripe-webhook
â · agora-token
â · generate-report (GPT-4o-mini)
â · create-checkout
â · process-payout
ââââââââââââââââââââ
íµì¬ ì€ê³ ìì¹
| ìì¹ | 구í |
|---|---|
| Black-box ì ì° | amount_usd(íì) vs payout_krw(íí°) â ë§ì§ìš ë¹ê³µê°, Edge Functionììë§ ê³ì° |
| íë«íŒ ìŽí ë°©ì§ | Agora ìžì± ìì± + ì°ëœì² ê³µì DB ížëŠ¬ê±° ìë ê²œê³ |
| AI 늬í¬íž = Lock-in | ìžì± ìì± ìì ììë§ ëŠ¬í¬íž ìì±, ìžë¶ íµí ë¶ê° |
| ë°ëªš 몚ë íŽë°± | Supabase / Agora 믞ì€ì ì ì êž°ë¥ ë°ëªš ëì |
ðïž íë¡ì íž êµ¬ì¡° (Project Structure)
Oho-Mate/
âââ public/
â âââ robots.txt
â âââ sitemap.xml
âââ src/
â âââ constants/index.js # ìì(C), í°íž(PX/KR), íê·ž, ë±êž ìì
â âââ data/tutors.js # íí° ëª©ì
ë°ìŽí°
â âââ context/
â â âââ UserContext.jsx # Supabase Auth + ë°ëªš ì ì
â â âââ WishlistContext.jsx # ì° ëª©ë¡ (localStorage)
â â âââ XPContext.jsx # XP + ë 벚 + ë°°ì§ + XPToastPortal
â â âââ NotificationContext.jsx # ìžì± ì늌
â âââ lib/
â â âââ supabase.js # Supabase íŽëŒìŽìžíž
â â âââ openai.js # GPT-4o-mini 늬í¬íž + ë°ëªš íŽë°±
â â âââ chat.js # Realtime ì±í
(구ë
·ì ì¡Â·ë°ëªš ë°ìŽí°)
â â âââ xp.js # XP ì 늜·조í·ì€ížëŠÂ·ë°°ì§ íšì
â âââ hooks/
â â âââ useAgora.js # Agora RTC CDN ë¡ë + ì±ë ì¡°ìž/늬ëž
â âââ components/
â â âââ Nav.jsx # ë°ìí ë€ë¹ê²ìŽì
â â âââ BottomNav.jsx # 몚ë°ìŒ íëš íë°
â â âââ Footer.jsx # íží° (ìœêŽÂ·ëšìŽì¥ ë§í¬)
â â âââ VoiceRoom.jsx # Agora ìì± UI (50ë¶ íìŽëšž, ì°žê°ì)
â â âââ XPBar.jsx # XP ì§í ë° + LevelBadge
â â âââ Box / Btn / Chip / Stars / Modal / Toast / Avatar / ...
â â âââ CRT.jsx # ì€ìºëŒìž ì€ë²ë ìŽ
â â âââ ErrorBoundary.jsx
â â âââ ProtectedRoute.jsx
â âââ pages/
â â âââ Home.jsx # ê²ì íìŽë¡, ê²ì í¬íž, AI 늬í¬íž í
, ë¹êµí
â â âââ TutorsList.jsx # ê²ì·íí°Â·ì ë ¬
â â âââ TutorDetail.jsx # About/Schedule/Reviews í
â â âââ Booking.jsx # Stripe ê²°ì 3ëšê³
â â âââ Dashboard.jsx # ìì
íí©/AI늬í¬íž/ìì늬ì€íž/XPë¡ê·ž
â â âââ TutorDashboard.jsx # íí° ìì
êŽëЬ + ê°ìŽë í
â â âââ Messages.jsx # Supabase Realtime ì±í
â â âââ ReportDetail.jsx # AI 늬í¬íž ììž + íëì칎ë + íŽìŠ
â â âââ LessonRoom.jsx # ìžì± ìì± ìì
룞 (Agora + ë
žíž + 늬í¬íž)
â â âââ Vocab.jsx # íêµìŽ ê²ì ëšìŽì¥ 84ê°
â â âââ Admin.jsx # êŽëЬì íšë
â â âââ Terms.jsx # ìŽì©ìœêŽ (í/ì)
â â âââ Privacy.jsx # ê°ìžì 볎ì²ëŠ¬ë°©ì¹š (í/ì)
â âââ modals/
â â âââ AuthModal.jsx # ë¡ê·žìž/íìê°ì
â â âââ ApplyModal.jsx # íí° ì§ìì
â â âââ OnboardingModal.jsx # ì ê· ê°ì
ìšë³Žë©
â âââ App.jsx # BrowserRouter + 몚ë ëŒì°íž
âââ supabase/
â âââ config.toml
â âââ migrations/
â â âââ 00001_initial.sql # profiles, packages, lessons, reviews, ai_reports, notifications
â â âââ 00002_chat_xp_games_badges.sql # chat, xp_ledger, streaks, badges + triggers
â âââ functions/
â âââ _shared/
â â âââ supabase-admin.ts
â â âââ cors.ts
â â âââ exchange-rate.ts
â âââ create-checkout/ # Stripe Checkout Session ìì±
â âââ stripe-webhook/ # ê²°ì ìë£ â lessons + chat room ìë ìì±
â âââ generate-report/ # GPT-4o-mini AI íìµ ëŠ¬í¬íž v2
â âââ agora-token/ # Agora AccessToken2 (HMAC-SHA256, pure Deno)
â âââ process-payout/ # íí° ì ì° ì²ëЬ
âââ index.html # OG / Twitter Card / JSON-LD SEO
ð ïž êž°ì ì€í (Tech Stack)
| ë¶ë¥ | êž°ì | ì©ë |
|---|---|---|
| Frontend | React 18 + Vite 5 | SPA ë ëë§ |
| Routing | React Router v6 | íŽëŒìŽìžíž ëŒì°í |
| Auth & DB | Supabase | ìžìŠ Â· PostgreSQL · RLS |
| Realtime | Supabase Realtime | ì€ìê° ì±í 구ë |
| Edge Functions | Deno (Supabase Edge) | ê²°ì ·í í°Â·ëЬí¬ížÂ·ì ì° ìë²ëŠ¬ì€ |
| Payment | Stripe Elements + Webhooks | íší€ì§ ê²°ì |
| Voice | Agora RTC (CDN 4.20.0) | ìžì± ìì± ìì |
| AI | OpenAI GPT-4o-mini | íìµ ëŠ¬í¬íž ìì± |
| Styling | Inline CSS | íœì ìíž ëììž ìì€í |
| State | React Context + localStorage | ì ì ìí |
| SEO | Open Graph · JSON-LD · sitemap | ê²ììì§ ìµì í |
ðïž DB ì€í€ë§ (íµì¬ í ìŽëž)
-- Migration 00001
profiles -- ì ì íë¡í (id, name, av, role, game_tags, level)
tutor_applications -- íí° ì§ìì (name, discord, lang, tags, intro, status)
packages -- ìì
íší€ì§ (name, lessons, price_usd, payout_krw)
lessons -- ìì
(learner_id, tutor_id, status, amount_usd, payout_krw, exchange_rate, platform_profit)
reviews -- 늬뷰 (lesson_id, learner_id, tutor_id, rating, text)
ai_reports -- AI 늬í¬íž (lesson_id, report_json[v2 schema])
notifications -- ìžì± ì늌 (user_id, type, title, body, metadata)
-- Migration 00002
chat_rooms -- ì±í
룞 (participants uuid[], last_message, last_message_at)
chat_messages -- ë©ìì§ (room_id, user_id, content, type, metadata)
-- type: "text" | "system" | "warning"(ì°ëœì² ê³µì ê°ì§)
xp_ledger -- XP íë êž°ë¡ (user_id, action, xp, label)
streaks -- ì°ì íìµìŒ (user_id, current_streak, longest_streak, last_login)
game_profiles -- ê²ì íë¡í (user_id, game_id, username, rank, server)
badges -- ë°°ì§ ì ì (10ì¢
ìë ë°ìŽí°)
user_badges -- íë ë°°ì§ (user_id, badge_id)
XP íë í ìŽëž
| ì¡ì | XP | ì€ëª |
|---|---|---|
SESSION_COMPLETE | +50 | ìì ìë£ |
REVIEW_WRITTEN | +30 | 늬뷰 ìì± |
FLASHCARD_DONE | +15 | íëì칎ë ì 첎 ìë£ |
QUIZ_PERFECT | +25 | íŽìŠ ë§ì |
DAILY_LOGIN | +10 | ë§€ìŒ ì²« ì ì |
STREAK_3 | +20 | 3ìŒ ì°ì |
STREAK_7 | +100 | 7ìŒ ì°ì |
REPORT_READ | +5 | 늬í¬íž ìŽë |
ð€ AI 늬í¬íž v2 ì€í€ë§
interface ReportV2 {
// Core
date: string;
tutor: string;
topic: string;
level: "ì
묞" | "ìŽêž" | "ì€êž" | "ê³ êž";
duration_min: number;
// ê²ì 컚í
ì€íž
game_context: string; // "ë¡€ ìë í°ìŽ ì¹êžì ìíµ" ë±
highlight_moment: string; // ìì
ì€ ë² ì€íž ìê°
vocab_mastery_pct: number; // 0~100 ìŽí ìŽíŽë
// íìµ ë¶ì
vocabulary: { word, meaning, roman, example, game_usage }[];
cultural_notes: { title, body }[]; // 묞íì ë§¥ëœ
pronunciation_tips: { tip, example }[]; // ë°ì êµì í¬ìžíž
good: string; // ìí ì
improve: string; // ê°ì ì
next_lesson: string; // ë€ì ìì
ì¶ì²
homework: string; // 곌ì
overall_score: number; // 1~10
}
ð ììíêž° (Getting Started)
1. ì ì¥ì íŽë¡
git clone https://github.com/octxxiii/Oho-Mate.git
cd Oho-Mate
2. íší€ì§ ì€ì¹
npm install
3. í겜 ë³ì ì€ì
cp .env.example .env
.env íìŒì ìŽìŽ ìë ê°ë€ì ì±ì죌ìžì:
# Supabase (https://supabase.com)
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
# Stripe (https://stripe.com)
VITE_STRIPE_PUBLIC_KEY=pk_test_...
# OpenAI (https://platform.openai.com)
VITE_OPENAI_API_KEY=sk-...
# Agora (https://console.agora.io)
# Edge Function í겜ë³ì â Supabase Dashboard > Functions > Secrets
# AGORA_APP_ID=your-app-id
# AGORA_APP_CERTIFICATE=your-certificate (ììŒë©Ž no-auth 몚ë)
# Stripe (Edge Functionì©)
# STRIPE_SECRET_KEY=sk_live_...
# STRIPE_WEBHOOK_SECRET=whsec_...
â ïž ëªšë í겜 ë³ì ììŽë ë°ëªš 몚ëë¡ ì êž°ë¥ ì€í ê°ë¥í©ëë€.
- Supabase 믞ì€ì â ë°ëªš ë¡ê·žìž + ë¡ì»¬ ì€í 늬ì§
- OpenAI 믞ì€ì â ìí AI 늬í¬íž ë°í
- Agora 믞ì€ì â no-auth 몚ë (í í° ììŽ ì±ë ì ì)
4. Supabase ë¡ì»¬ ì€í (ì í)
# Supabase CLI íì
supabase start
supabase db reset # ë§ìŽê·žë ìŽì
00001 + 00002 ì ì©
5. ê°ë° ìë² ì€í
npm run dev
ëžëŒì°ì ìì http://localhost:5173 ìŽêž°
ð Edge Functions ë°°í¬
# ì 첎 íšì ë°°í¬
supabase functions deploy
# ê°ë³ íšì
supabase functions deploy stripe-webhook
supabase functions deploy agora-token
supabase functions deploy generate-report
supabase functions deploy create-checkout
supabase functions deploy process-payout
# í겜 ë³ì ì€ì
supabase secrets set STRIPE_SECRET_KEY=sk_live_...
supabase secrets set STRIPE_WEBHOOK_SECRET=whsec_...
supabase secrets set AGORA_APP_ID=...
supabase secrets set AGORA_APP_CERTIFICATE=...
supabase secrets set OPENAI_API_KEY=sk-...
Stripe Webhook ìëí¬ìžíž
POST https://<project>.supabase.co/functions/v1/stripe-webhook
ìŽë²€íž:
- checkout.session.completed â lessons ìì± + chat_room ìë ìì±
- payment_intent.succeeded â íŽë°± (checkout 믞ì²ëЬ ì)
ðºïž ì€íëŠ°íž ë¡ëë§µ
â Sprint 1 â Core Platform (ìë£)
- Agora RTC ìžì± ìì± ìì
(
/lesson/:id) - AI 늬í¬íž v2 (ê²ì 컚í ì€íž + 묞í ë žíž + ë°ì í)
- íëì칎ë + íŽìŠ ëªšë (늬í¬íž ììž)
- Supabase Realtime ì±í (ì°ëœì² ê³µì ì°šëš ížëŠ¬ê±°)
- XP + ì€ížëŠ + ë°°ì§ ìì€í
- Stripe ê²°ì í ìë ì±í 룞 ìì±
- íêµìŽ ê²ì ëšìŽì¥ (84ê° íí, 5ê° í)
- êŽëЬì íšë (ììµ ë¶ì + íí° ì¬ì¬)
- ìŽì©ìœêŽ + ê°ìžì 볎ì²ëŠ¬ë°©ì¹š (í/ì)
- SEO (OG tags, JSON-LD, robots.txt, sitemap.xml)
ð Sprint 2 â Growth
- Stripe Subscription (ìê° ë¬Žì í íší€ì§)
- ìì ì ë ìŽë©ìŒ / ížì ì늌
- íí° ë¹ëì€ ìêž°ìê° (Supabase Storage)
- ê²ì ê³ì ì°ë (LoL API, VALORANT API)
- 늬í¬íž PDF ë€ìŽë¡ë
- 몚ë°ìŒ ì± (React Native)
ð® Sprint 3 â Scale
- AI íí° ì¶ì² (íìµ êž°ë¡ êž°ë°)
- 귞룹 ë ìš (3~5ëª )
- 컀뮀ëí° íŒë (íìµ ìžìŠÂ·ê²ì ì§€)
- ë€êµìŽ ì§ì (EN / JA / ZH)
- íí° ììµ ëì볎ë ê³ ëí
ð 볎ì & íë«íŒ 볎íž
| ìí | ëì |
|---|---|
| ì°ëœì² ê³µì ì°í | DB ížëŠ¬ê±° flag_contact_info â Discord/KakaoTalk/ìŽë©ìŒ íšíŽ ê°ì§ ì type: "warning" ë©ìì§ |
| ìžë¶ ìì±íµí ì ë | Agora ìžì± ìì± + AI 늬í¬ížë¥Œ ìžì± ìì ì ì©ìŒë¡ ì í |
| ì ì° êžì¡ ë žì¶ | payout_krw / platform_profit 칌ëŒì Edge Function + Adminë§ ì ê·Œ |
| JWT ìì¡° | 몚ë Edge Functionì Supabase JWT ê²ìŠ (verify_jwt = true) |
| Stripe ìì¡° ìì² | HMAC ìëª
ê²ìŠ (stripe.webhooks.constructEventAsync) |
ð ëŒìŽì ì€ (License)
MIT © 2025 OHO-MATE
<div align="center"> <b>ð¹ïž êž°ë¡ëì§ ìë ê²ì ê³µë¶ê° ìëë€</b><br/> <sub>Every lesson. Every word. Every level up â tracked forever.</sub><br/><br/> <sub>Made with â€ïž for Korean learners worldwide</sub> </div>