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