尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Next.js Hello World prototype for Vercel
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A small party-planning app: create a party, share invite links, and collect RSVPs (yes, maybe, or no, optional comment, guest counts).
Built on Next.js App Router. Locally it uses a SQLite file at ./data/invite.db. On Vercel without Turso it uses a temporary file:/tmp/invite.db so previews load; that data can disappear between serverless instances. Set a free Turso database for production.
npm install
cp .env.example .env.local
npm run dev
Open http://localhost:3000.
| Name | Required | Purpose |
|---|---|---|
NEXT_PUBLIC_APP_URL | Recommended | Base URL for RSVP and claim links, e.g. http://localhost:3000 or https://your-app.vercel.app. On Vercel, VERCEL_URL is used if this is empty. |
SMTP_HOST | To send email | SMTP server. Resend: smtp.resend.com. |
SMTP_PORT | Optional | SMTP port. Default 465 (TLS from the start). 587 uses STARTTLS. |
SMTP_USER | To send email | SMTP username. Resend: resend. |
SMTP_PASS | To send email | SMTP password. Resend: your API key. |
MAIL_FROM | To send email | From address, e.g. [email protected] or an address on a verified domain. |
FROM_NAME | Optional | From display name (default Partyz). Paired with MAIL_FROM, or with GMAIL_USER on the legacy path. |
GMAIL_USER | Legacy fallback | Gmail address. Used only when the SMTP variables above are not all set. |
GMAIL_APP_PASSWORD | Legacy fallback | Gmail App Password. The from address is GMAIL_USER. |
TURSO_DATABASE_URL | Production on Vercel | Turso database URL (libsql://…). Locally, omit this to use ./data/invite.db. On Vercel without this, the app uses /tmp/invite.db (ephemeral). |
TURSO_AUTH_TOKEN | With Turso URL | Turso auth token. |
Party images live in the same database as events (local ./data/invite.db or Turso). No extra blob-storage keys are required. Do not use ephemeral /tmp files for images.
Do not commit .env.local. Copy .env.example and fill in values.
SMTP_HOST=smtp.resend.com, SMTP_PORT=465, SMTP_USER=resend, and SMTP_PASS to that API key.MAIL_FROM to [email protected] for testing, or to an address on a domain you have verified in Resend.FROM_NAME (default Partyz).Resend’s testing sender only delivers to the email address on your Resend account until a domain is verified. Invite, sign-in, and host-email confirmation messages all need a verified MAIL_FROM domain before they can reach anyone else. If a send fails, the organizer notice includes the provider’s error.
If SMTP_HOST, SMTP_USER, SMTP_PASS, and MAIL_FROM are not all set, the app falls back to Gmail:
GMAIL_APP_PASSWORD. Spaces are fine.GMAIL_USER to that Gmail address. Mail is sent as GMAIL_USER.If SMTP is not configured, creating a party still works. The success screen always shows a copyable dashboard URL. You can add invitees and copy each unique RSVP link from the organizer page. Email CTAs stay in the background until mail is configured.
Vercel serverless has no persistent disk. Without Turso env vars the app still starts and uses /tmp/invite.db so previews work; a banner warns that data is temporary. For production, set Turso so events and RSVPs persist:
TURSO_DATABASE_URL and a token into TURSO_AUTH_TOKEN (Vercel project env vars).NEXT_PUBLIC_APP_URL to your Vercel URL, e.g. https://your-app.vercel.app./e/…/manage?t=…) once, copyable, as a backup. This browser also remembers the new party./host/claim?token=…). A signed-in host can open /e/…/manage without the secret. manage?t= still works./host/recover sends one sign-in link for every party on that email. The link expires in 30 minutes, is single-use, and is consumed when you press Continue (opening the link does not use it up). The session cookie lasts 30 days. The page always shows the same confirmation, whether or not the email has parties.name, email, and optional email2 (download a template from the manage page). Copy the link to share (email sending is optional). Invite mail is sent as “{host} via Partyz” and replies go to the host email.Each new party stores host_email, a unique host_claim_token, and host_claimed_at (null until opened).
/host/claim?token=… marks the party claimed and redirects to /e/{id}/manage?t={admin_token}.created_at.manage?t= auth are unchanged.Existing databases get new columns and tables on startup. CREATE TABLE IF NOT EXISTS does not alter a table that is already there, so the app reads PRAGMA table_info and runs ALTER TABLE … ADD COLUMN only when a column is missing. That is safe to repeat on local SQLite and Turso. No separate migration command is required.
Columns added this way:
events.host_email, events.host_claim_token, events.host_claimed_atevents.party_image_mime, invitees.email2events.allow_maybe (default 0 for parties that already existed; new parties set it from the form, on unless the host turns it off), events.timezone, events.ends_at, events.updated_at, events.host_email_verified_atevents_host_emailNew tables: host_login_tokens (one-time sign-in links, 30-minute expiry, only the SHA-256 hash is stored; recover links are limited to 3 per email per hour, create links to 10 per email per hour, and both share a cap of 30 per IP per hour), host_sessions (30-day cookie sessions), host_email_changes (confirm a new host email; previous_email is the address at request time), and host_device_grants (this browser can reopen a party it created, with expires_at). A one-time schema_flags row turns Maybe off for parties created before that row's timestamp. Party images also use an event_images table (bytes stay out of ordinary event reads). display_name stays the family or guest label. One invitee row is still one token and one RSVP. Rows saved before email2 existed keep a null second address and the same link. Changing the host email requires a signed-in session for the current address. The current address is notified, and the new address must confirm the link. A party with no host email can gain one only from the browser that created it, not from a dashboard link. A new sign-in link cancels older unused sign-in links for that email, and a new create link cancels older unused create links. The two budgets stay separate.
Sign-in and recovery mail use the same SMTP settings as invites. There are no new environment variables. With Resend, MAIL_FROM must be on a domain you have verified, or messages only reach the Resend account owner.
Invite card and party image URLs include ?v= set from events.updated_at (or created_at when a party has never been edited), so a browser does not keep a year-old card after the date or photo changes. RSVP and dashboard pages send noindex. Guest links use the party title, date, and place for link previews.
npm run dev # local
npm run build # production build
npm start # run the production build
npm test # unit tests (CSV import, party images, family email, mail config)