尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A community gallery of AI-built templates plus a browser editor for remixing them. See PLAN.md for the architecture, data model and phase checklist.
Status: Phases 1 (Foundation) and 2 (Gallery) complete: auth, profiles, landing page, uploads with licenses and rights confirmation, sandboxed previews, source browser, likes, saves, follows, filters, reports, DMCA form, admin review queue, and 29 starter templates.
Step-by-step setup, updating, and the launch checklist: docs/DEPLOYMENT.md.
Next.js 16 (App Router, Cache Components) · TypeScript strict · Tailwind CSS 4 · Supabase (Postgres, Auth, Storage) · Drizzle ORM · Upstash rate limiting · Vitest + PGlite · GitHub Actions · Vercel.
Requirements: Node 22+ and pnpm 10 (corepack enable installs pnpm).
pnpm install
cp .env.example .env.local # then fill in the values, see below
pnpm db:migrate # create tables
pnpm storage:setup # create storage buckets
pnpm seed # load the 29 starter templates
pnpm dev # http://localhost:3000
The app starts without any keys: the landing page and legal pages work, sign-in shows a "not set up" message and the waitlist says it isn't open yet. Add the Supabase keys to turn those on.
Preview origin locally: http://localhost:3000 is the app and http://127.0.0.1:3000 acts as the separate preview domain. They're different sites to the browser, so isolation works the same way it will in production.
Everything is listed with instructions in .env.example. Only NEXT_PUBLIC_* values reach the browser. AI and payment keys are server-only and CI fails the build if one shows up in the client bundle.
| Variable | Needed for | Where to get it |
|---|---|---|
NEXT_PUBLIC_APP_URL | Links, metadata | Your domain, e.g. https://remaxx.ai |
NEXT_PUBLIC_PREVIEW_ORIGIN | Sandboxed previews | Your second domain, e.g. https://remaxxusercontent.com |
NEXT_PUBLIC_SUPABASE_URL | Auth, storage | Supabase → Project Settings → API Keys |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | Auth in the browser | Same page (publishable / anon key) |
SUPABASE_SECRET_KEY | Storage admin (server) | Same page (secret / service_role key) |
DATABASE_URL | Everything with data | Supabase → Connect → connection string |
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN | Shared rate limits | Upstash console (optional until launch) |
OPENAI_API_KEY | Moderation, vibe search | platform.openai.com (optional; without it uploads are marked unchecked and search matches words only) |
ANTHROPIC_API_KEY | Claude in the editor | console.anthropic.com → API Keys (optional; Claude models show "not set up" without it) |
GOOGLE_GENERATIVE_AI_API_KEY | Gemini in the editor | aistudio.google.com → Get API key (optional) |
DEEPSEEK_API_KEY | DeepSeek in the editor | platform.deepseek.com → API keys (optional) |
AI_ACCESS | Who can use AI features | admins (default) or signed-in. Plans are only sold to people who can use AI |
STRIPE_SECRET_KEY | Selling plans | Stripe → Developers → API keys. Test key (sk_test_...) until launch |
STRIPE_WEBHOOK_SECRET | Credits after payment | Stripe → Developers → Webhooks → endpoint → Signing secret (whsec_...) |
STRIPE_ALLOW_LIVE | Real charges | Leave unset. Live keys are refused unless this is |
.env.local.http://localhost:3000/auth/callback and https://<your-domain>/auth/callback to Redirect URLs.
Auth → Emails → Templates: paste the two templates in docs/email-templates.md so sign-in links work in any browser and include a typeable code.NEXT_PUBLIC_AUTH_PROVIDERS (e.g. google,microsoft,apple); their buttons stay hidden until you do.pnpm db:migrate and pnpm storage:setup. No terminal access to your database? Run pnpm db:setup-sql, paste the output into Supabase → SQL Editor and click Run; it does the same thing and is safe to run twice.pnpm seed, or pnpm seed:sql and paste the output into the SQL Editor.pnpm db:make-admin <your-handle>.| Command | What it does |
|---|---|
pnpm dev | Dev server |
pnpm build / pnpm start | Production build / serve it |
pnpm lint | ESLint (no any without an explicit, commented disable) |
pnpm typecheck | Generates route types, then tsc --noEmit (strict) |
pnpm test | Unit and integration tests. Integration tests run real SQL against an in-process Postgres (PGlite); no database needed |
pnpm db:migrate | Applies new files in db/migrations to DATABASE_URL |
pnpm db:make-admin <handle> [--revoke] | Grants or removes the admin role |
pnpm storage:setup | Creates or updates the storage buckets in config/limits.ts |
pnpm seed / pnpm seed:sql | Loads the starter templates into DATABASE_URL, or prints the SQL to paste. Safe to run again |
pnpm db:setup-sql | Prints all migrations plus storage buckets as one SQL script for the Supabase SQL Editor |
pnpm check:bundle | After a build, fails if a secret-looking value is in the browser bundle |
pnpm verify | Everything CI runs, in order |
app/ Routes (landing, explore, project pages, upload, profiles, saved, admin, legal, preview origin)
components/ UI kit, layout, gallery cards, project page pieces, landing visuals
config/ Site settings, legal versions, licenses and remix rules, tools/categories/styles, limits
lib/ auth, db, licensing (remix rules, credit chain), projects, upload (validate, scan), moderation, seed, security
db/migrations/ Plain SQL migrations, the source of truth for the schema
scripts/ migrate, seed, make-admin, storage setup, setup SQL, bundle secret scan
seed/ Starter template files and their catalog (titles, licenses, tags)
tests/ unit/ and integration/ (PGlite)
No browser access to tables. Every table has row level security on with no policies and no grants to the browser roles. The server talks to Postgres directly and checks permissions with the tested helpers in lib/auth/permissions.ts.
Sessions are verified. getClaims() validates the Supabase JWT on every request; nothing trusts an unverified cookie.
Untrusted code never runs on the server. Project previews are served as plain files from a separate domain with a sandbox CSP, and only ever run in the visitor's browser. The app domain refuses to be framed.
Rate limits on every write endpoint (Upstash when configured, in-memory otherwise).
Uploads are untrusted. Every file is checked by path, type, size and content (magic bytes, valid UTF-8), and scanned for leaked secrets (rejected) and malware or phishing patterns (held for admin review). Text and the cover image go through OpenAI moderation when a key is set.
Licenses are enforced. Every upload needs a license and a rights confirmation, recorded per project. Remixes can only use licenses every ancestor allows (config/licenses.ts, tested in tests/unit/licensing.test.ts).
blobs.storage_key.<preview origin>/v/<version id>/<path> inside a sandboxed iframe. Only published projects are served there.project_search: a plain-language look and feel description, the text search matches against (title, description, category, tool, style and topic tags, look and feel), and an embedding of that text (text-embedding-3-small, pgvector).seed/vibes.ts). For uploads, lib/search/hints.ts reads the CSS/HTML for clues (dark background, frosted glass, hard shadows, serif type...) and a small model turns code + clues into two or three sentences. With no AI key, the clues alone become the description.lib/search/rank.ts blends vibe similarity (55%), word coverage (40%) and a small popularity nudge (5%). The same function produces the "why it matched" chips. Everyday words map onto filters: "glassmorphism" counts as Glassy, "admin" as Dashboard./admin.lib/search/rank.ts; tests/unit/search-rank.test.ts pins the expected top result for real queries over the starter templates./admin (admins only). Admins can dismiss a report, remove a project, or approve held uploads.lib/projects/remix.ts): same files (no bytes copied, blobs are shared by hash), credit to every ancestor, and the most permissive license the chain allows. Drafts only count as remixes once they're published./edit/<id>) has a chat panel (text, voice through the browser's speech recognition, reference images, model picker) and a workspace with a live preview and a CodeMirror code view.lib/editor/bundle.ts) and posted to a blank runner page on the preview origin (<preview origin>/run), which runs under the same sandbox as published previews. Unsaved edits show instantly; nothing runs on the app origin.lib/ai/pipeline.ts): sign-in and AI_ACCESS, model set up, per-minute rate limit, per-person daily cap, site-wide daily budget, one request at a time, prompt moderation, then the model call with a timeout. Every attempt is logged in ai_messages with tokens and estimated cost.lib/ai/edit-protocol.ts): SEARCH/REPLACE edits or whole-file writes. The answer is parsed and applied to a copy of the files, path-checked (no escaping the project, no touching images), and shown as a per-file diff. Nothing is saved until the person applies it.lib/projects/versions.ts). Undo restores the previous version as a new one, so nothing is lost. Saves are rejected if the draft changed in another tab, and a draft can only reuse files from its own history./api/explain) writes a plain-English tour of a version and caches it, so each template is explained once and then free to read for everyone./create, lib/projects/new-project.ts) starts a private draft from one of the original starters in lib/projects/starters.ts (blank page, landing page, portfolio, link page, small app). If the person describes what they want, the description waits in the editor's chat; nothing is sent (or charged) until they press Send. Creating shares the remix rate limit and the 50-draft cap./edit/<id>/publish, lib/projects/publish.ts) turns a draft into a gallery template. It runs the same checks as an upload (secret scanner, moderation of the text and cover), only offers licenses the whole credit chain allows (a CC BY-SA ancestor keeps every remix CC BY-SA; Personal Use stays Personal Use), records the person's rights confirmation, and keeps the "Remixed from" credit, which can't be removed. Flagged remixes are held for review.config/plans.ts has the plans (price, monthly credits, model tier, rate limits), the markup (2.5×), what a credit is worth ($0.01) and the free prompts (2). Change a plan's price by editing it and bumping its priceVersion; Stripe prices can't be edited, so a new version makes a new price.credit_ledger (updates and deletes are refused by the database). credit_accounts.balance is kept in the same transaction and can never go below zero. Every row has a unique idempotency key, so retried webhooks and requests can't apply twice.lib/ai/pipeline.ts → lib/billing/credits.ts): the editor shows an estimate first. The server holds up to the maximum the request could cost, calls the model, then charges the actual cost (never more than the hold) and releases the rest. Failures, timeouts and unusable answers are refunded in full. With no credits left, requests stop (a free prompt is used instead if one is left, on Starter-tier models).AI_ACCESS). With AI_ACCESS=admins, only admins see working plan buttons, so you can test checkout without anyone paying for something they can't use./admin shows credits charged this month against estimated provider cost, and lets admins add or remove credits by handle (recorded in the ledger with a note).sk_test_...) into STRIPE_SECRET_KEY on Vercel.https://<your app domain>/api/stripe/webhook, events checkout.session.completed, customer.subscription.created, customer.subscription.updated, customer.subscription.deleted, invoice.paid. Copy its Signing secret (whsec_...) into STRIPE_WEBHOOK_SECRET./api/health: payments should say ok: test mode./pricing, pick a plan and pay with card 4242 4242 4242 4242, any future date, any CVC. /billing should show the plan and its credits within a few seconds.Going live later means a live key plus STRIPE_ALLOW_LIVE=true, a live-mode webhook, and AI_ACCESS=signed-in. Don't do it before the Terms and Privacy pages have had a lawyer's review.
instrumentation.ts, instrumentation-client.ts): server errors through Next's onRequestError, browser errors through the SDK. Collection is locked down (sentryDataCollection() in lib/monitoring/scrub.ts: no cookies, bodies, AI prompts, database values or stack-frame variables), and every report also passes scrubSentryEvent. No session replays. Source maps aren't uploaded yet; add withSentryConfig and a SENTRY_AUTH_TOKEN when readable stack traces are worth it.lib/monitoring/analytics.ts): page views plus six events (project_created, remix_started, ai_prompt_sent, ai_change_applied, published, checkout_started). Memory-only persistence (no cookies, no consent banner needed), no person profiles, no recordings, Do Not Track respected, URLs scrubbed. Events never carry typed text. Add one by extending AnalyticsEvent and calling track().MODELS in config/models.ts: a stable id, the label people see, the provider, the provider's apiModel name, whether it reads images (vision), its plan tier, and its price per million input/output tokens.lib/ai/providers.ts (request shape, response parsing, error mapping), its key in lib/env.ts and lib/ai/server.ts, an entry in PROVIDERS in config/models.ts, and a test in tests/unit/ai-providers.test.ts.apiModel and redeploy. The model's id stays the same, so history and usage stay linked.trueNEXT_PUBLIC_SENTRY_DSN | Error reports (optional) | sentry.io → Project → Settings → Client Keys (DSN). Off when unset |
NEXT_PUBLIC_POSTHOG_KEY, NEXT_PUBLIC_POSTHOG_HOST | Product analytics (optional) | posthog.com → Project settings → Project API key. Off when unset |
VIBE_DESCRIBE_MODEL | Style descriptions | Optional; defaults to gpt-5-mini |
config/limits.ts (AI_LIMITS). Admins see today's AI usage and spend on /admin.