尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Your next favorite thing is already out there — a peer-to-peer barter marketplace (item-for-item, bundles, or item + negotiated cash).
Stack: one Next.js 15 app (App Router) — UI and API (src/app/api/v1) — on MongoDB (Mongoose). No separate backend.
src/app pages + the API (src/app/api/v1/[[...path]]/route.ts)
src/server API logic: models, offers, deals, chat, moderation …
src/shared Zod schemas + enums/state machines used by UI and API
src/components UI components src/lib client helpers (api, auth, toast)
scripts/ seed.ts, reset-demo.ts, demo-photos/ (credits)
public/demo demo listing photos
pnpm install
cp .env.example .env.local # fill MONGODB_URI + JWT_ACCESS_SECRET (the only env file)
pnpm seed # optional demo data (use a dev database such as …/swapd_dev, never your live one)
pnpm dev # http://localhost:3000
Demo logins (after seeding): [email protected], [email protected], [email protected], [email protected] (admin: [email protected]) — password swapd-demo-pass.
MONGODB_URI, JWT_ACCESS_SECRET (32+ random chars), and for photo uploads either CLOUDINARY_URL (Cloudinary → Settings → API Keys → copy the "API environment variable" and replace the placeholders) or BLOB_READ_WRITE_TOKEN (Vercel Storage → Blob). Cloudinary wins if both are set.0.0.0.0/0 (Vercel IPs change).pnpm test runs 42 API/flow tests (auth, offers & revisions, offer↔chat sync, deals & reviews, listings, security) against an in-memory MongoDB replica set — your real database is never touched. pnpm typecheck checks client and server. See docs/AUDIT.md for the offer/message/deal model and the verification checklist.
Email + password sign-up, sign-in with rotating refresh tokens, email verification (link emailed on sign-up; the profile gets a verified badge), forgot password (one-time link, 1 h expiry, only the newest link works, all sessions signed out after a reset), and change password. Reset requests are rate-limited (3 per hour per address) and answer identically for unknown addresses.
Emails go through, in order: RESEND_API_KEY → SMTP_* → console (dev only). Easiest free setup — Gmail:
SMTP_HOST=smtp.gmail.com, SMTP_PORT=465, [email protected], SMTP_PASS=<app password>, MAIL_FROM="SWAPD <[email protected]>".APP_URL to your site's public URL (links in emails use it, never request headers). On Vercel add all of these under Environment Variables and redeploy.Gmail limits you to ~500 emails/day, which is fine for a prototype. For a real launch use a domain + Resend/SES so mail doesn't land in spam.
/listing/[id], ISR 60 s, with share-preview metadata) and the first screen of /discover (ISR 30 s). The landing hero is server-rendered with CSS-only motion; animated sections load lazily.pnpm dev pages fetch their data from the browser, so every /api/v1/... call shows in DevTools → Network (Fetch/XHR). Server-rendered first loads only apply to production builds.?public=1, added automatically by the client when signed out) send s-maxage=30, stale-while-revalidate=300; everything personalised is private, no-store. Static demo photos are immutable./auth/* returns the user, saving a round trip; one 15 s /pulse request drives badges and toasts; open chat threads fetch only messages newer than the last one (?after=).INDEX_VERSION in src/server/db.ts) because Mongoose auto-indexing is off in production; small connection pool for serverless.pnpm typecheck (client + server projects) runs as part of pnpm build.ListingLock index makes it impossible for two active deals to hold one item.