TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Practice for a job interview with an AI interviewer. Pick a role and experience level, answer five generated questions, and get live-streamed feedback with scores on each answer.
Live demo: https://interview-prep-platform-xy36.vercel.app
The API runs on a free host, so the first request after a quiet period can take up to a minute. Sign-in is Google only.
GET /api/api-token) and sends it as Authorization: Bearer <token>. The API verifies it (HS256, issuer and audience pinned, expiry) and takes the user id only from the token.InterviewSession (mapped to the sessions table) so it doesn't clash with NextAuth's Session.| Layer | Tools |
|---|---|
| Frontend | Next.js (App Router), TypeScript, Tailwind CSS, Framer Motion |
| Auth | NextAuth with Google OAuth and the Prisma adapter |
| Backend | Node.js, Express |
| Database | PostgreSQL (Neon), Prisma |
| AI | Google Gemini |
| Hosting | Vercel (web), Render (API) |
backend/ Express API: sessions, answers, Gemini service, rate limiters
frontend/ Next.js app: home, new interview, interview page, dashboard
All routes except /health need Authorization: Bearer <token>.
| Method | Path | What it does |
|---|---|---|
| GET | /health | Health check |
| GET | /api/sessions | Your sessions, newest first (replaces /api/sessions/user/:userId) |
| GET | /api/sessions/:id | One session with questions and answers |
| POST | /api/sessions | Create a session: { role, experienceLevel } |
| PATCH | /api/sessions/:id/complete | Finish a session: { overallScore } |
| DELETE | /api/sessions/:id | Delete a session |
| POST | /api/answers | Submit an answer, feedback streams back: { questionId, answerText } |
backend/, create .env with DATABASE_URL, GEMINI_API_KEY, API_AUTH_SECRET, FRONTEND_ORIGIN and PORT. Then run npm install, npx prisma migrate dev and npm run dev.frontend/, create .env.local with DATABASE_URL, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, AUTH_SECRET, NEXT_PUBLIC_API_URL and API_AUTH_SECRET. Then run npm install and npm run dev.Both folders have a .env.example listing these variables.
| Variable | Where | What it is for |
|---|---|---|
DATABASE_URL | both | Postgres connection string |
GEMINI_API_KEY | backend | Gemini API key |
GEMINI_MODEL | backend | Optional. Gemini model for questions and feedback, default gemini-3.6-flash. Empty or blank uses the default |
GEMINI_FALLBACK_MODEL | backend | Optional. Tried when the main model is overloaded (503), out of quota (429) or times out, default gemini-3.5-flash-lite. Empty or blank uses the default |
API_AUTH_SECRET | both | Signs (web) and verifies (API) the sign-in tokens |
FRONTEND_ORIGIN | backend | Web app URLs allowed by CORS, comma-separated, no trailing slash |
PORT | backend | API port, default 5000 |
TRUST_PROXY_HOPS | backend | Number of proxies in front of the API in production, 1 to 5, default 1. On Render it must be 3 (measured: visitor, Cloudflare, Render proxy); a wrong value makes every visitor share one IP counter |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | frontend | Google sign-in |
AUTH_SECRET | frontend | NextAuth secret (NEXTAUTH_SECRET also works) |
NEXT_PUBLIC_API_URL | frontend | API URL |
API_AUTH_SECRET must be the same on both sides, at least 32 characters, different from the NextAuth secret, and never prefixed with NEXT_PUBLIC_. The API won't start without it or FRONTEND_ORIGIN. To generate one: node -e "console.log(require('crypto').randomBytes(36).toString('base64url'))"
To run the auth tests, create a separate database branch (Neon: Branches, Create branch from your default branch), set it as TEST_DATABASE_URL in backend/.env, and run npm run test:auth in backend/. They check that missing or bad tokens get 401 and that one user can't read, change, delete or answer in another user's session. The script refuses to run if TEST_DATABASE_URL is the same as DATABASE_URL or on the same host.
npm run test:config, npm run test:ratelimit, npm run test:model and npm run test:retry in backend/ need no database and never call Gemini.
Deploy the API (Render) first, then the web app (Vercel), with the same API_AUTH_SECRET on both and the Vercel URL in FRONTEND_ORIGIN. The new API closes the security hole on its own, and the new web app only works with it because it sends a token instead of a user id. Until the web app is redeployed, the old one gets 401 errors.
Khizar Islam Rathore, Software Engineering student at the University of Karachi. GitHub: github.com/Khizar-Islam | LinkedIn: linkedin.com/in/khizar-islam-rathore