尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证A premium global automotive marketplace
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A premium international automotive marketplace with a cinematic real-time 3D hero, an interactive 3D showroom, real search and filtering, buyer accounts, private-seller and dealership tools, and a moderated administration area.
Stack: Next.js 16 (App Router, Turbopack) · React 19 · TypeScript · Tailwind CSS 4 · Three.js · React Three Fiber · drei · GSAP + ScrollTrigger · Supabase (Auth, Postgres, Storage) · Vercel.
npm install
cp .env.example .env.local # optional — the site runs without it
npm run dev # http://localhost:3000
Without Supabase credentials the app runs in preview mode: the marketplace, search, filters, vehicle pages, collections, compare and the 3D showroom all work against clearly-labelled demonstration inventory. Accounts, enquiries, seller tools and admin show an explanatory notice until Supabase is configured.
| Command | What it does |
|---|---|
npm run dev | Development server |
npm run build / npm start | Production build / server |
npm run lint · npm run typecheck | ESLint · TypeScript |
npm run db:test | Applies all migrations + seed to a throwaway local PostgreSQL and runs the security test suite |
npm run db:test:pglite | Same suite on PGlite (PostgreSQL compiled to WASM) — no PostgreSQL install needed. TWICE=1 also checks the hardening migration is idempotent |
npm run test:e2e | Playwright end-to-end tests (BASE_URL=http://localhost:3000; set CHROMIUM_PATH if needed) |
npm run test:unit | Unit tests for security helpers (safe redirects) |
npm run test:a11y | axe-core WCAG 2.1 A/AA audit of public pages at desktop and mobile widths (BASE_URL, CHROMIUM_PATH) |
npm run seed:generate | Regenerates supabase/seed.sql from the demo inventory |
npm run admin:grant -- [email protected] | Grants admin rights (needs the service-role key) |
npm run photos | Downloads the demo-listing photographs listed in tools/photos/manifest.mjs from Wikimedia Commons, blurs plates, crops and writes WebP + credits |
npm run renders | Re-renders the hero/showroom fallback stills of the 3D concept car |
.env.local (see .env.example).supabase link then supabase db push) or by pasting each file into the SQL editor:
supabase/migrations/20261009000000_core_schema.sql — tables, triggers, RLS policies, search functionsupabase/migrations/20261009000100_storage.sql — vehicle-images and dealer-logos buckets + policiessupabase/migrations/20261009000200_showroom_assets.sql — the licensed 3D concept-car assetsupabase/migrations/20261009000300_hardening.sql — security hardening (USD reference protection, anonymous quotas, upload ownership, function permissions)supabase/seed.sql, and set NEXT_PUBLIC_SHOW_DEMO_INVENTORY=true. Do not run the seed in production. Remove demo data any time with
delete from auth.users where email like '%@demo.motionx.invalid';
If you loaded an older seed (with /renders/demo/ images), run that delete and re-run supabase/seed.sql to pick up the photographs.NEXT_PUBLIC_SITE_URL; add https://your-domain/auth/callback to Redirect URLs.?code=); token-hash templates pointing at /auth/callback?token_hash={{ .TokenHash }}&type=… also work.insert into public.admin_users (user_id, note)
select id, 'founder' from auth.users where email = '[email protected]';
or npm run admin:grant -- [email protected].active/sold listings from active sellers. Enquiries and inspection requests are readable only by the buyer, the receiving seller and admins. Buyer profiles and private contact data are never public.admin_users, which no client can write.pending_review; material edits to a live listing return it to review (platform_settings.listing_moderation = required | auto). Every status change is written to moderation_actions.private.consume_rate_limit, not exposed via the API).npm run db:test exercises all of this against real PostgreSQL (91 assertions; Supabase's auth/storage schemas are stubbed — see supabase/tests/00_supabase_stubs.sql).
Original asking prices are always shown unchanged in the seller's currency. To enable clearly-labelled estimates and cross-currency price filtering/sorting:
EXCHANGE_RATES_PROVIDER=open-er-api (ExchangeRate-API open access — includes AED) or frankfurter (ECB reference rates — no AED).SUPABASE_SERVICE_ROLE_KEY and CRON_SECRET. vercel.json schedules /api/cron/exchange-rates daily; it stores rates and recalculates each listing's USD reference price.Without a provider, the price filter compares listings in the selected currency only, and says so on the page.
Set NEXT_PUBLIC_PLAUSIBLE_DOMAIN to enable cookieless Plausible analytics. Events: search, listing_view, enquiry_submitted, inspection_requested, buyer_signup, seller_signup, listing_submitted, dealer_onboarding, showroom_open. No personal data is sent; visitors can opt out at /cookies.
Full launch checklist (accounts, every environment variable, database, domain and post-deploy smoke test): DEPLOYMENT.md.
.env.example (at least the Supabase URL/key and NEXT_PUBLIC_SITE_URL).vercel.json activates automatically when CRON_SECRET is set./models/* is served with immutable caching — if you replace the GLB, give it a new filename and update vehicle_3d_assets.url.
| Asset | Source | Licence | Action needed |
|---|---|---|---|
public/models/concept-car.glb (hero + showroom) | “Car Concept” by Eric Chadwick / Darmstadt Graphics Group GmbH (2024), from the Khronos glTF-Sample-Assets repository, based on a CC0 model by “Unity Fan” | CC BY 4.0 — attribution required | Keep the credit on /credits and the showroom page. Khronos logo surfaces were removed; textures recompressed (WebP, 1024 px) and geometry meshopt-compressed: 11.8 MB → 3.4 MB. |
public/photos/demo/*, public/photos/banners/* | Wikimedia Commons photographs of the same make, model and generation as each demo listing (author and licence per file in src/lib/demo/photos.generated.json) | CC BY / CC BY-SA / public domain | Credited under each photo and on /credits. Labelled "Representative photo — not the vehicle listed". Plates blurred, cropped/extended to 3:2, WebP. Regenerate with npm run photos. |
public/renders/hero-fallback*.webp, OG image | Captured from the live hero scene (tools/qa/capture-poster.mjs) | Derived from the CC BY model | — |
Adding a 3D model to a listing: upload a licensed .glb (meshopt or uncompressed; not Draco), insert a vehicle_3d_assets row with credit/licence and supported paint_options, then set vehicles.asset_id. Only listings with an asset show the 3D action. Paint swatches appear only when the asset declares them; the runtime recolours materials whose names start with Paint 1.
src/app/(site)/ Pages: home, /cars, /cars/[slug], /collections, /showroom, /sell, /dealers,
/account, /dashboard, /admin, auth & legal pages
src/app/actions/ Server actions (public forms, auth, seller tools, admin)
src/app/api/cron/ Exchange-rate job
src/components/ Design system (ui/), home, vehicles, three (R3F), dashboard, admin, forms
src/config/ Site, markets (countries/currencies), vehicle taxonomy & collections
src/lib/data/ Data access (Supabase or demo backend), mappers
src/lib/ Auth (DAL), validation (zod), rates, rate limiting, analytics
supabase/ Migrations, seed, database tests
tools/photos/ Demo-listing photo pipeline (Commons → plates blurred → WebP + credits)
tools/studio-renderer/ Renderer for the 3D concept car's fallback stills
tools/qa/ Playwright E2E tests, screenshots, poster capture
npm run db:test:pglite (PGlite / PostgreSQL 18.3), not yet on a real Supabase project.npm run lint, npm run typecheck and npm run build pass./contact), not self-service.