尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A calm, mobile-first Secret Santa app. Invite people with one link, share wishlists, set the rules, and let Giftr draw names. Everyone finds out who they're shopping for, and nobody else does.
Production is giftr.christmas. Pushes to main deploy there. Every other branch gets a preview deployment.
Next.js 16 (App Router, Server Actions, src/proxy.ts), React 19, TypeScript, Tailwind CSS v4 and shadcn/ui, Better Auth (Google, Facebook, email sign-in links), Postgres with Drizzle ORM, Resend with React Email, and Vercel Cron. Tests use Vitest with fast-check (including property-based tests of the draw engine) and Playwright.
You need Node 22+, pnpm, and Docker (or any Postgres 16+).
pnpm install
docker compose up -d # Postgres with `giftr` and `giftr_test` databases
cp .env.example .env.local # then set BETTER_AUTH_SECRET: openssl rand -base64 32
pnpm db:migrate
pnpm db:seed # optional: demo users and an exchange
pnpm dev
Open http://localhost:3000. Without RESEND_API_KEY, emails aren't sent. Instead they appear at http://localhost:3000/dev/outbox, so you can sign in as anyone (seeded users are [email protected], [email protected], [email protected], [email protected] and [email protected]) by requesting a sign-in link and opening it from the outbox. Google and Facebook buttons appear once their credentials are set.
pnpm lint
pnpm typecheck
pnpm test # unit and property-based tests
pnpm build && pnpm test:e2e # end-to-end tests against the giftr_test database
The end-to-end suite walks four people through a whole exchange (create, invite by email and link, join, wishlists, a household and an exclusion, the draw, each reveal, and the anonymous chat), checks that the organizer can't see pairings and that Santas stay anonymous in the UI, the database and emails, and runs axe accessibility checks along the way.
WALKTHROUGH=1 pnpm test:e2e walkthrough records a desktop and a phone walkthrough to test-results/walkthrough/.
| Command | What it does |
|---|---|
pnpm db:generate | Create a migration after changing src/db/schema.ts |
pnpm db:migrate | Apply migrations (uses DATABASE_URL_UNPOOLED when set) |
pnpm db:studio | Browse the database with Drizzle Studio |
To run the daily job locally: curl -H "Authorization: Bearer $CRON_SECRET" http://localhost:3000/api/cron/daily.
Import the repo at vercel.com/new. vercel.ts sets the build command (pnpm db:migrate && pnpm build, so every deploy applies pending migrations) and the daily cron.
Add Neon from the Vercel Marketplace (Storage → Neon Postgres) and connect it to the project. It sets DATABASE_URL and DATABASE_URL_UNPOOLED. Turn on "Create a database branch for each preview deployment" so previews never touch production data.
Add Resend from the Marketplace (or create an API key at resend.com) and set RESEND_API_KEY. In Resend, verify the domain you'll send from, then set EMAIL_FROM, for example Giftr <[email protected]>. Until a domain is verified, Resend only delivers to your own address.
Set the remaining environment variables (Settings → Environment Variables):
| Variable | Environments | Value |
|---|---|---|
BETTER_AUTH_SECRET | All | openssl rand -base64 32 |
BETTER_AUTH_URL | Production only | https://giftr.christmas |
NEXT_PUBLIC_APP_URL | Production only | https://giftr.christmas |
CRON_SECRET | All | openssl rand -hex 32 (Vercel Cron sends it automatically) |
CONTACT_EMAIL | All | Shown on the privacy and terms pages |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | Production | See below |
FACEBOOK_CLIENT_ID, FACEBOOK_CLIENT_SECRET | Production | See below |
Leave BETTER_AUTH_URL and NEXT_PUBLIC_APP_URL unset for previews; they use their own deployment URL automatically.
Deploy from main. That branch is production. Then smoke test: open the site, sign in with an email link, create an exchange, and check that the invite email arrives. In the project's Cron Jobs tab you can trigger manually.
giftr.christmas is the production domain (www.giftr.christmas redirects to it). Use that host everywhere below.
https://giftr.christmas/privacy and https://giftr.christmas/terms. The email, profile and openid scopes are all Giftr needs. Publish the app when you're ready for anyone to sign in.https://giftr.christmas (and http://localhost:3000 for local testing)https://giftr.christmas/api/auth/callback/google (and http://localhost:3000/api/auth/callback/google)GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.https://giftr.christmas/api/auth/callback/facebook. Make sure the email permission is enabled.giftr.christmas, the privacy policy URL to https://giftr.christmas/privacy, the terms URL to https://giftr.christmas/terms, and the user data deletion instructions URL to https://giftr.christmas/privacy#delete.FACEBOOK_CLIENT_ID and FACEBOOK_CLIENT_SECRET, then switch the app to Live.Accounts are linked by email, so someone invited by email who later signs in with Google or Facebook lands in the same account.
Google and Facebook only redirect to registered URLs, so on preview deployments use email sign-in links. Previews need RESEND_API_KEY to send them; the dev outbox is disabled on every Vercel deployment because it would expose working sign-in links.
src/
app/ (marketing)/ (auth)/ (app)/ join/[code]/ unsubscribe/ api/ dev/outbox/
components/ app components; ui/ holds the shadcn primitives
db/ schema.ts, index.ts, seed.ts
emails/ React Email templates
lib/ auth, authz, draw/ (the draw engine), email/, link-preview, validation
server/ server-only queries and Server Actions
proxy.ts keeps signed-out visitors out of app pages
e2e/ Playwright tests
drizzle/ SQL migrations
vercel.ts build command and cron
/api/cron/daily