Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
A full-stack job portal built with Next.js 15 (App Router), Prisma, PostgreSQL, Tailwind CSS v4 and Socket.IO. Job seekers browse and apply to roles, upload a résumé, track application status and message employers. Companies post jobs, review applicants, move them through a hiring pipeline and reply in-app.查看完整 README ↗
A full-stack job portal built with Next.js 15 (App Router), Prisma, PostgreSQL, Tailwind CSS v4 and Socket.IO.
Job seekers browse and apply to roles, upload a résumé, track application status and message employers. Companies post jobs, review applicants, move them through a hiring pipeline and reply in-app.
Powered by Gemini — all optional, see AI.md:
Install dependencies
npm install
Configure the environment
cp env-template.txt .env
Fill in every value. At minimum you need DATABASE_URL, JWT_SECRET and the three
CLOUDINARY_* variables. Generate secrets with openssl rand -base64 48.
GEMINI_API_KEY is optional. Without it the portal runs exactly as it does
today — match scores simply do not appear and search falls back to keyword
filtering. With it, run a one-off backfill after your first migration:
POST /api/ai/reindex as an ADMIN user.
Set up the database
npm run db:generate
npm run db:migrate
Two migrations run here. 20260910120000_harden_schema adds unique constraints
on (userId, jobId) for applications and (userId, companyId) for conversations;
it de-duplicates existing rows first, keeping the earliest of each pair, so
take a backup before running it against real data. 20260910130000_ai_embeddings
then adds the vector tables and the AI-derived profile columns — that one is
purely additive.
Run it
npm run dev:both # Next.js + the Socket.IO server
# or separately:
npm run dev
npm run dev:socket
Open http://localhost:3000.
| Script | What it does |
|---|---|
npm run dev | Next.js dev server |
npm run dev:socket | Standalone Socket.IO server |
npm run dev:both | Both of the above |
npm run build | prisma generate then next build |
npm run typecheck | tsc --noEmit |
npm run lint | ESLint (flat config) |
npm run db:migrate | Apply migrations in development |
npm run db:deploy | Apply migrations in production |
npm run db:studio | Prisma Studio |
app/
├── api/ # Route handlers — every one authorises via lib/auth.ts
├── auth/ # Sign in / register
├── company/ # Company dashboard and profile
├── seeker/ # Seeker dashboard, profile and messages
├── jobs/ # Public feed, job detail, post and edit
├── applications/ # Company applicant review
├── conversations/ # Company messaging
├── components/ # Navbar, NotificationBell, Toast, ThemeProvider, ui kit
└── hooks/ # useAuthGuard
lib/ # auth, clientAuth, validation, prisma, env, socketContext
├── ai/ # Gemini: embeddings, matching, semantic search
middleware.ts # Edge routing guard for protected pages
prisma/ # Schema and migrations
store/ # Redux store and slices
All routes return JSON. Errors are { "error": "<human-readable message>" }.
Authentication is a JWT sent either as the token cookie or an
Authorization: Bearer <token> header; every mutating route authorises the
caller server-side — ownership is never taken from the request body.
| Method | Route | Access |
|---|---|---|
POST | /api/auth | Public — action: register | login | logout |
GET | /api/auth | Authenticated — returns the current session |
GET | /api/jobs | Public feed of active jobs |
GET | /api/jobs?companyId= | Owning company — includes applicants |
POST | /api/jobs | Company — companyId comes from the session |
GET | /api/jobs/:id | Public — adds hasApplied / isOwner when signed in |
PUT PATCH DELETE | /api/jobs/:id | Owning company |
GET | /api/applications | Seeker: own only · Company: own jobs only |
POST | /api/applications | Seeker — userId from the session |
PATCH | /api/applications | Owning company — notifies the applicant |
DELETE | /api/applications | Applicant (withdraw) or owning company |
GET POST | /api/conversations | Participants only; requires an existing application |
GET POST | /api/messages | Conversation participants only |
GET PATCH DELETE | /api/notifications | Own notifications only |
GET POST DELETE | /api/resumes | Own résumé; readable by companies you applied to |
ADMIN role cannot be self-assigned at registration; grant it directly in the database.SameSite=Lax, Secure in production. Treat XSS as session-compromising and keep the CSP tight.middleware.ts is a routing convenience only — it decodes the JWT without verifying the
signature, because jsonwebtoken cannot run on the edge runtime. Real authorisation is in the
API routes.SOCKET_EMIT_SECRET and SOCKET_ALLOWED_ORIGINS in production
and refuses to start without them, so nobody can forge chat messages into a room.See AI.md for the full design.
See AUDIT.md for the record of issues found and fixed in the
hardening pass, and DEPLOYMENT.md for hosting instructions.
GET/api/users/:id |
| Full record for self; minimal public shape otherwise |
PUT DELETE | /api/users/:id | Self or admin — PUT re-issues the JWT |
GET | /api/stats | Public — counts for the homepage |
GET | /api/jobs/recommended | Seeker — roles ranked against their profile |
POST | /api/ai/resume | Seeker — parse their résumé into a profile |
POST | /api/ai/assist | Company — draft a description, extract skills |
GET POST | /api/ai/reindex | Admin — index health, backfill embeddings |