🎓

AI Web App Course

reankh.org · Google AI Studio · Supabase



ទំនាក់ទំនង Admin

លោក ហុន ម៉ុម · @mrhonmom

មាតិការ

🎓

AI Course · reankh.org

🏁 ផ្នែកទី ១

សៀវភៅសិក្សា AI Web App

វគ្គនេះសិស្សនឹងសាងសង់ WebApp ប្រើ Gemini AI ភ្ជាប់ Supabase (Project ចាស់ ប្រើជាមួយ @reankh_bot) Deploy ឡើង Vercel · reankh.org

🤖

Gemini AI

🔐

Supabase Auth

💾

Database

🚀

Vercel

📌 Goal: WebApp ពិត · Login · AI Chat · Save · Video · Deploy Online
🔑 ផ្នែកទី ២

គណនី & API Key

💻 Software

  • ✅ Visual Studio Code
  • ✅ Google Chrome
  • ✅ Git
  • ✅ Node.js v20+

🌐 Accounts

  • ✅ Gmail (Google AI Studio)
  • ✅ GitHub
  • ✅ Vercel (reankh.org)
  • ✅ Supabase (Project ចាស់)

📄 ឯកសារ .env.local

NEXT_PUBLIC_GEMINI_API_KEY=AIzaSy_YOUR_KEY
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...
TELEGRAM_BOT_TOKEN=YOUR_BOT_TOKEN
TELEGRAM_CHAT_ID=YOUR_CHAT_ID
⚠️ .env.local មិនត្រូវ Push ទៅ GitHub ឡើយ! ត្រូវ Add ក្នុង Vercel Dashboard
📁 ផ្នែកទី ៣

Project Structure

ai-webapp/
├── app/
│   ├── layout.js
│   ├── page.js
│   ├── login/page.js
│   ├── dashboard/page.js
│   ├── chat/page.js
│   ├── videos/page.js        ← Video page
│   └── api/
│       ├── chat/route.js     ← Gemini API
│       └── telegram/route.js
├── components/
│   ├── VideoPlayer.js        ← Protected player
│   └── ProtectedRoute.js
├── lib/
│   ├── supabase.js
│   └── gemini.js
├── .env.local
└── package.json
npx create-next-app@latest ai-webapp --js --tailwind --app --no-src-dir
cd ai-webapp
npm install @google/generative-ai @supabase/supabase-js
npm run dev
🔐 ផ្នែកទី ៤

Supabase Auth (ភ្ជាប់ Project ចាស់)

ប្រើ Supabase Project ដែលភ្ជាប់ @reankh_bot — Copy URL & Anon Key ពី Dashboard → Settings → API
// lib/supabase.js
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
// app/login/page.js
'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
import { supabase } from '@/lib/supabase'

export default function LoginPage() {
  const router = useRouter()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [mode, setMode] = useState('login') // 'login' | 'register'
  const [error, setError] = useState('')

  async function handleSubmit(e) {
    e.preventDefault()
    setError('')
    const fn = mode === 'register'
      ? supabase.auth.signUp({ email, password })
      : supabase.auth.signInWithPassword({ email, password })
    const { error } = await fn
    if (error) setError(error.message)
    else router.push('/dashboard')
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={e=>setEmail(e.target.value)} required />
      <input type="password" value={password} onChange={e=>setPassword(e.target.value)} required />
      {error && <p className="text-red-400">{error}</p>}
      <button type="submit">{mode === 'login' ? 'Login' : 'Register'}</button>
      <button type="button" onClick={()=>setMode(m=>m==='login'?'register':'login')}>
        {mode === 'login' ? 'Register' : 'Login'}
      </button>
    </form>
  )
}
🤖 ផ្នែកទី ៥

Gemini AI Chat

// app/api/chat/route.js
import { GoogleGenerativeAI } from '@google/generative-ai'
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY)

export async function POST(request) {
  const { message, history } = await request.json()
  const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' })
  const chat = model.startChat({ history: history || [] })
  const result = await chat.sendMessage(message)
  return Response.json({ reply: result.response.text() })
}
👁️ ផ្នែកទី ៦

AI Image Reader (Vision)

// app/api/vision/route.js
import { GoogleGenerativeAI } from '@google/generative-ai'
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY)

export async function POST(request) {
  const formData = await request.formData()
  const file = formData.get('image')
  const prompt = formData.get('prompt') || 'អ្វីដែលឃើញ?'
  const bytes = await file.arrayBuffer()
  const base64 = Buffer.from(bytes).toString('base64')
  const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' })
  const result = await model.generateContent([
    { inlineData: { mimeType: file.type, data: base64 } },
    prompt
  ])
  return Response.json({ reply: result.response.text() })
}
💾 ផ្នែកទី ៧

Save ទៅ Supabase

-- Supabase SQL Editor — Run នេះ
create table if not exists ai_chats (
  id uuid default gen_random_uuid() primary key,
  user_id uuid references auth.users(id) on delete cascade,
  role text not null check (role in ('user','model')),
  message text not null,
  created_at timestamptz default now()
);
alter table ai_chats enable row level security;
create policy "User owns chats" on ai_chats for all
  using (auth.uid() = user_id)
  with check (auth.uid() = user_id);

-- Video table
create table if not exists videos (
  id uuid default gen_random_uuid() primary key,
  title text not null,
  description text,
  video_url text not null,
  thumbnail_url text,
  sort_order int default 0,
  is_active boolean default true,
  created_at timestamptz default now()
);
alter table videos enable row level security;
create policy "Anyone logged in can view videos" on videos
  for select using (auth.uid() is not null and is_active = true);
📱 ផ្នែកទី ៨

Telegram + AI

// app/api/telegram/route.js
export async function POST(request) {
  const { message } = await request.json()
  const res = await fetch(
    `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`,
    { method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ chat_id: process.env.TELEGRAM_CHAT_ID,
        text: message, parse_mode: 'HTML' }) }
  )
  return Response.json(await res.json())
}
🚀 ផ្នែកទី ៩

Deploy · reankh.org

git init && git add . && git commit -m "feat: AI webapp"
git branch -M main
git remote add origin https://github.com/honmomis/ai-webapp.git
git push -u origin main
# បន្ទាប់ Import ក្នុង Vercel → Add Env Vars → Deploy
✅ ផ្នែកទី ១០

Checklist

🎬 វីដេអូ Course

🎬

Loading videos...