尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Turns app screenshots into animated promo videos, rendered on a canvas in the browser. Next.js on Vercel, Supabase (auth + Postgres), Cloudflare R2 (files), Paddle (billing). Architecture, conventions and every dashboard setting live in CLAUDE.md; this file covers running it and operating it.
cp .env.example .env.local # fill in values (see comments in the file)
npm install
npm run dev # http://localhost:3000
npm run visual-regression # after any rendering change (see CLAUDE.md rule 6)
Free accounts can store 200 MB of files (screenshots, icons, music), Pro
accounts 5 GB (maxStorageBytes in src/lib/plan.ts). The limit is
enforced on the server when an upload is approved
(/api/storage/upload → public.reserve_storage, migration 0019), so it
can't be bypassed from the browser. Usage shows on /account, on
/projects and in the editor's slide rail. Deleting a project frees its
space immediately; files a project no longer uses (replaced screenshots,
deleted slides) are cleaned up an hour after they stop being used,
whenever the user's usage is recounted.
After running migration 0019 once, record files that already existed:
node --env-file=.env.local scripts/backfill-storage-usage.mjs.
Every Sunday at 03:17 UTC, .github/workflows/db-backup.yml:
Backs up production with pg_dump (scripts/backup/backup-db.mjs) to
the private R2 bucket nimina-backups, under weekly/<YYYY-MM-DD>/:
data.sql.gz: every row of every table in public and auth (users,
sign-in identities, projects, billing records, …);public-schema.sql.gz: our schema exactly as it was in production;supabase-schemas.sql.gz: Supabase's own auth/storage schemas,
used only by the restore check below;manifest.json: row count and content checksum of every table, taken
in the same database snapshot as the dump.It keeps the newest 8 backups and deletes older ones.
Proves the backup restores (scripts/backup/verify-backup.mjs). It
downloads the backup it just uploaded, runs the restore procedure below
into a throwaway Postgres 17, and compares every table's row count and
contents with the manifest. Any difference fails the run, and GitHub
emails the repo owner. The result is saved next to the backup as
verify.json. It also reports drift, meaning any difference between
production's schema and what supabase/migrations/ builds.
Run it on demand: GitHub → Actions → Database backup → Run workflow.
See what you have: node --env-file=.env.local scripts/backup/fetch-backup.mjs --list.
Not in the backup: uploaded files (they're in R2, not the database), and Supabase dashboard settings (auth providers, email templates, SMTP, URL configuration; see CLAUDE.md "Accounts & sign-in").
Restoring means loading the data into a new Supabase project and pointing
the app at it. You need the PostgreSQL 17 client tools (psql) and the
Supabase CLI.
node --env-file=.env.local scripts/backup/fetch-backup.mjs --date=2026-10-04 --out=./restore
Leave out --date to get the newest. You can also download the files
from Cloudflare (R2 → nimina-backups → weekly/<date>/).export NEW_DB_URL='postgresql://postgres.<new-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres'
supabase link --project-ref <new-ref>
supabase db push
psql "$NEW_DB_URL" -v ON_ERROR_STOP=1 -c "do \$\$ declare t text; begin for t in select format('%I.%I', schemaname, tablename) from pg_tables where schemaname = 'public' loop execute 'truncate ' || t || ' cascade'; end loop; end \$\$;"
gunzip -c restore/data.sql.gz | PGOPTIONS='-c session_replication_role=replica' psql "$NEW_DB_URL" -v ON_ERROR_STOP=1 --quiet
ok:
node scripts/backup/check-restore.mjs --manifest=restore/manifest.json --db="$NEW_DB_URL"
NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY and
SUPABASE_SERVICE_ROLE_KEY to the new project's values, both in
Vercel and in .env.local, then redeploy.SUPABASE_DB_URL (GitHub secret) to the new project.The weekly check runs steps 3–6 against a stand-in project, so a green run means this exact procedure works on that week's data.
nimina-backups (private, no public
URL). Then create an API token with Object Read & Write limited to
that one bucket. Don't reuse the app's token: the app should never be
able to read the backups.db.<ref>.supabase.co host is IPv6-only,
and GitHub's runners can't reach it.SUPABASE_DB_URL (the session pooler string)R2_ACCOUNT_IDR2_BACKUP_ACCESS_KEY_IDR2_BACKUP_SECRET_ACCESS_KEYFree Supabase projects pause after 7 days without activity. A daily Vercel
Cron (vercel.json → /api/cron/keepalive) runs one real query. It needs
CRON_SECRET set in Vercel (any long random string); Vercel sends it
automatically, and the route refuses every other caller. The weekly backup
is a second, independent source of activity.