尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证LurkStack — a real, deployable, multi-user text-only social feed (Next.js 15, Better Auth, Drizzle, Neon Postgres, Playwright)
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
A real, deployable, multi-user text-only social feed — built for the MarkTrack
Agentic Engineer Intern assessment.
Guests can read everything. Any signed-in user can post, comment, react, and
edit or delete any post, regardless of who wrote it. That last rule is
deliberate and unusual; it is implemented exactly as specified, with no
ownership check anywhere in the codebase.
Every value lives in .env.local (gitignored). .env.example ships with empty
placeholders only — no real secret is ever committed.
Monitoring is additive. With no Telegram or Puter configuration the app behaves
identica查看完整 README ↗A real, deployable, multi-user text-only social feed — built for the MarkTrack Agentic Engineer Intern assessment.
Guests can read everything. Any signed-in user can post, comment, react, and edit or delete any post, regardless of who wrote it. That last rule is deliberate and unusual; it is implemented exactly as specified, with no ownership check anywhere in the codebase.
| Concern | Choice |
|---|---|
| Framework | Next.js 15 (App Router), React 19 |
| Language | TypeScript, strict |
| Styling | Tailwind CSS v4, shadcn/ui-style primitives (Radix), Lucide |
| Auth | Better Auth 1.7 (email + password, Drizzle adapter) |
| Database | PostgreSQL (Neon) via Drizzle ORM + pg |
| Tests | Playwright (21 end-to-end tests) |
| Deploy | Netlify |
npm install
cp .env.example .env.local # then fill in the values below
npm run db:migrate # create the schema
npm run db:seed # 8 users, 40 posts, 39 comments, 140 likes
npm run dev # http://localhost:3000
Every value lives in .env.local (gitignored). .env.example ships with empty
placeholders only — no real secret is ever committed.
| Variable | Required | Purpose |
|---|---|---|
DATABASE_URL | yes | PostgreSQL / Neon connection string |
BETTER_AUTH_SECRET | yes | Session signing secret |
BETTER_AUTH_URL | yes | Public base URL the auth handler trusts |
NEXT_PUBLIC_APP_URL | yes | Public base URL for the browser auth client |
TELEGRAM_BOT_TOKEN | no | Alert delivery; app works without it |
TELEGRAM_CHAT_ID | no | Alert destination |
PUTER_AUTH_TOKEN | no | Optional AI summary of an incident |
CRON_SECRET | no | Bearer token for /api/cron/health |
AUTH_RATE_LIMIT_WINDOW | no | Credential throttle window, seconds (default 300) |
AUTH_RATE_LIMIT_MAX | no | Credential throttle attempts (default 60) |
Monitoring is additive. With no Telegram or Puter configuration the app behaves identically — alerts are simply not sent.
Created by npm run db:seed, password Password123! for both:
| Name | |
|---|---|
| Aisha Rahman | [email protected] |
| Yusuf Khan | [email protected] |
These are documented here and in the seed output only. The public login page
is a plain login form and never displays demo credentials, development hints, or
a "demo accounts" block. (tests/auth.spec.ts asserts this.)
Six further seeded users, 40 posts, 39 comments and 140 likes make the feed look like something people actually use.
Two rules, both enforced server-side from the Better Auth session. The client is never trusted for identity.
1. Any authenticated user can mutate any post.
editPost and deletePost in lib/actions/posts.ts resolve the current user,
verify a session exists, and then act. There is no authorId === user.id
comparison anywhere in the repository — by design. The Edit and Delete menu
items are likewise never hidden based on ownership.
2. Guests can read, never write.
/, /u/[id], posts, comments and counts are all publicly readable. Every
mutation returns UNAUTHENTICATED for a guest and is recorded as a blocked
authorization event. In the UI, a guest action opens an authentication gate
dialog that links to /login and /signup with a next parameter, rather than
failing silently.
| Route | Access | Notes |
|---|---|---|
/ | public | Server-rendered feed, newest first |
/u/[id] | public | Public profile + that user's posts |
/login | public | Email + password |
/signup | public | Name, email, password |
/api/auth/[...all] | public | Better Auth handler |
/api/health | public | Machine-readable health, no secrets |
/api/cron/health | CRON_SECRET | Scheduled health probe |
The UI is honest about the network, not optimistic to a fault:
online/offline events plus request outcome.lib/monitor/ records structured audit events to the audit_event table:
signup · login success/failure · logout · create/edit/delete post · comment · like/unlike · blocked unauthenticated mutations · auth/session anomalies · unexpected server errors · database errors.
Design rules, all of which are load-bearing:
lib/monitor/rules.ts assigns severity from the event
itself. AI never decides what happened; it may only summarise.allowed, never a violation. Guest mutation is
blocked and is a genuine authorization event.repeatCount; alerts render it as Repeated events: N.void record(...). Every send is wrapped and
failure-isolated; the request path never awaits Telegram or Puter.requestId./api/health returns real checks (database round-trip, required config) with
503 when unhealthy. /api/cron/health is a lightweight scheduled path guarded
by CRON_SECRET.
npx playwright test # 21 tests, ~1.2 min
Covers signup, login, logout, session persistence, guest feed, guest auth gate,
guest server-side rejection, create/edit/delete post, cross-user edit,
cross-user delete, comments, likes, duplicate-like prevention, profiles,
not-found, seeded data, and /api/health.
The two cross-user tests are permanent: they are the clearest expression of the specification, and deleting them would hide a regression.
npm run typecheck, npx next lint and npx next build are all clean.
Better Auth's limiter is enabled and real. It was tuned after a genuine bug:
the default global limit throttled /get-session as well as the credential
endpoints, so a signed-in user who made enough page loads began silently seeing
the guest UI. Credential endpoints keep a tight per-IP throttle; read-only
session checks get a much higher ceiling.
| Command | Purpose |
|---|---|
npm run dev | Development server |
npm run build | Production build |
npm run start | Serve the production build |
npm run typecheck | tsc --noEmit |
npm run lint | ESLint |
npm test | Playwright |
npm run db:generate | Generate a Drizzle migration |
npm run db:migrate | Apply migrations |
npm run db:seed | Reset and seed realistic data |
DATABASE_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL and
NEXT_PUBLIC_APP_URL (BETTER_AUTH_URL and NEXT_PUBLIC_APP_URL must be the
deployed HTTPS origin).CRON_SECRET variables.npm run db:migrate && npm run db:seed against the deployed database./api/health returns {"status":"ok"}.Intentionally not built: messaging, follows, notifications, admin, payments, file or image uploads, AI chat, and unrelated settings. Posts are text-only.