尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Open-source React e-commerce storefront. Prerendered for SEO with Product JSON-LD, CRO built in, and AI prompts that generate your backend. Runs on bundled demo data or your own API.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
A complete, production-shaped e-commerce front end. It runs on a bundled
catalogue out of the box, and on your own backend by changing one environment
variable.
Built by CodeCrafters. MIT licensed — fork it, rebrand
it, ship it.
No database, no API key, no account. The demo store works immediately.查看完整 README ↗A complete, production-shaped e-commerce front end. It runs on a bundled catalogue out of the box, and on your own backend by changing one environment variable.
Built by CodeCrafters. MIT licensed — fork it, rebrand it, ship it.
npm install
npm run dev # http://localhost:5173
No database, no API key, no account. The demo store works immediately.
Most storefront themes are either a static template you have to gut before it can hold real data, or a full platform you have to adopt wholesale. This is neither. It is a real storefront — filters, variants, stock, cart, discounts, checkout, orders, addresses — talking to one documented interface with two implementations behind it.
VITE_DATA_SOURCE=mock → src/lib/api/mock.js (bundled catalogue, localStorage)
VITE_DATA_SOURCE=api → src/lib/api/http.js (fetch against your server)
Nothing above src/lib/api/ knows which one is running. Design against the mock,
demo it to a client, then point it at a real backend without touching a
component.
docs/API.md is the whole specification. If your server answers those routes with those shapes, this works.
Alongside the data adapters sits a configuration document (GET /storefront)
that drives identity, currency, navigation, the entire home page,
recommendations and checkout. Between the two, almost everything a merchant
would want to change is data rather than code.
/admin — demo credential admin / admin.
A working back office: a full product record editor (details, media, variant matrix, fit and fabric, categories), inventory, category tree, shared size charts, orders, storefront settings, import and export. It is also the reference implementation of the write API, so every documented endpoint has a screen proving it works.
In mock mode it writes to a local database that the storefront reads, so an edit in admin shows on the shop immediately, with no publish step.
The documentation is served inside it at /admin/docs — the same markdown
files, rendered, with copy buttons on every prompt.
| Mode | Database | Backend |
|---|---|---|
mock | None — browser storage | None |
api | Someone else's | Odoo, Shopify, Medusa, WooCommerce |
api + your own | This schema | You build it, from the prompts |
Every page below is also served by the storefront itself at /docs — same
markdown, no second copy — and it is prerendered, so it is readable without
JavaScript and indexable. /docs/api carries a live explorer: pick an endpoint,
press Run, and read the JSON the adapter actually returns. On a demo that is the
bundled catalogue; pointed at your API it is a real request.
The link sits in the footer's utility bar while the shop runs on demo data and
disappears once it is pointed at a real backend — a shop selling shirts should
not offer its customers an API reference. features.docsLink overrides it
either way.
| docs/README.md | Index — start here |
| CHANGELOG.md | What changed, newest first |
| CONFIGURATION.md | Every setting: menu, home page, currency, features |
| API.md | Endpoint reference |
| DATA-MODEL.md | Every object shape |
| CHECKOUT.md | Payment integration, with Stripe and Razorpay examples |
| CRO.md | The trust and fit elements, and the research behind them |
| THEMING.md | Palette, type, logo, brand assets, image ratios |
| RECIPES.md | Odoo, Shopify, Medusa, WooCommerce mappings |
| ADMIN.md | The back office and the write API |
| PERFORMANCE.md |
| Route | What it is |
|---|---|
/ | Home — hero, categories, new in, editorial, collections, bestsellers |
/shop · /shop/:category | Catalogue with faceted filters, sort and pagination |
/collections/:slug | A curated set, same grid |
/product/:slug | Gallery, colour and size pickers with per-variant stock, fit panel, size chart, fabric and certifications, reviews with fit data, related, sticky buy bar |
/admin/* | Products, inventory, categories, orders, settings, import/export |
/search?q= | Free-text search |
/cart | Full bag, quantity, discount codes, free-shipping progress |
/wishlist | Saved items |
/checkout | Contact, address (with a state list per country), delivery method, payment step, order summary |
/checkout/return | Where a shopper lands after a gateway's hosted payment page |
/order/:id | Confirmation and receipt |
/account | Overview (latest order, details, default address, saved items), orders, address book |
/login | Sign in and register |
/pages/:slug | Size guide, shipping, care, contact — content built into the theme |
* | 404 |
Plus a slide-in cart drawer, a mobile filter sheet, and toasts.
cp .env.example .env.local
| Variable | Default | What it does |
|---|---|---|
VITE_DATA_SOURCE | mock | mock or api |
VITE_API_BASE_URL | — | Required when api. No trailing slash |
VITE_API_TIMEOUT | 12000 | Request timeout in ms |
VITE_API_CACHE | on | off shows backend edits on the next load. For development. Browser only — the build always caches |
VITE_STORE_NAME | LOOM | Wordmark and page titles |
VITE_CURRENCY | USD | ISO 4217 |
VITE_LOCALE | en-US | Number and date formatting |
VITE_FREE_SHIPPING_OVER | 150 | Threshold, in major units |
VITE_REPO_URL | this repo | Footer source link |
Vite inlines every
VITE_*variable into the shipped bundle. Anything here is public. Never put a secret key in one.
Switching to a real backend:
VITE_DATA_SOURCE=api
VITE_API_BASE_URL=https://api.yourstore.com/v1
The app fails at boot with a readable message if api is set without a base
URL, rather than silently making requests to undefined.
Money is integer minor units. { amount: 12800, currency: "USD" } is
$128.00. Never a float — 0.1 + 0.2 !== 0.3, and a cart that adds up in floats
is eventually a cent out on a real invoice. src/lib/money.js handles
formatting and zero-decimal currencies.
The cart is owned by the server. Every mutation returns the whole repriced cart and the client replaces state wholesale. Discounts, shipping thresholds and tax are server concerns; a client that recomputes them will disagree with the invoice sooner or later.
Facets come from the API, over the whole category. Deriving them from the visible results is the classic catalogue bug: filter to one colour and every other colour vanishes from the panel.
Responses are validated at the boundary. A 200 with a missing price throws
a ContractError naming the endpoint and the field. A wrong shape that passes
silently surfaces three components later as a null dereference and costs you an
afternoon.
Checkout stops before payment, deliberately. Card details must never touch a storefront theme — it drags your entire frontend into PCI scope. Hand off to Stripe Elements, Razorpay or Adyen and create the order server-side on the payment webhook.
Filter state lives in the URL. Shareable, bookmarkable, and survives the back
button. None of which you get from useState.
The apparel fields are the point. Size and fit cause roughly two thirds of
fashion returns, and apparel return rates run 20–40% — the highest of any
category. fit, fabric, sizeChart and per-review fit data all ship through
the API for that reason, and the reasoning is written up in
CRO.md with sources.
Requests are generation-guarded. Change a filter twice quickly and the slow first response cannot overwrite the fast second one.
One request for the first screen. GET /bootstrap returns settings,
categories, collections and the home rails together — five sequential round
trips become one. Reads then pass through a cache that de-duplicates in-flight
requests and serves stale-while-revalidating; writes purge only the namespaces
they could have touched. See PERFORMANCE.md.
The demo catalogue is its own chunk. In api mode those 34KB never leave
the server.
Every route sets its own metadata, and product pages emit Product
structured data with real availability and — only when there are reviews — an
aggregate rating.
npm run images fetches every image from Unsplash, crops it to the right
aspect, grades it to a common exposure so a hundred unrelated photos read as
one lookbook, and pins the chosen photo ids in scripts/images.lock.json so the
same commit always builds the same store.
Choosing a photograph is three checks, and each one exists because the catalogue used to fail it:
Chosen ids are unique across the run, so no two products share a photograph.
npm run images # fetch anything missing
npm run images:force # re-roll everything
npm run images -- --only=products/leather-belt # re-roll one slot
npm run images -- --candidates=categories/shirts # what the search offers, as JSON
To overrule the search for one slot, put "id": "<photo id>" in the lockfile
entry and delete that file from public/images/; the next run fetches your
photo and fills in the credit. --candidates is how you find the id.
Credits are written to public/images/CREDITS.md. Replace the whole folder with
real product photography when you have it — the shapes are 4:5 for products and
categories, 3:2 for collections, 16:9 for the hero.
src/
lib/
api/
index.js the switch — asserts both adapters match
mock.js bundled backend
http.js real backend
contracts.js types + boundary validation
config.js every env var, resolved once
money.js minor units, formatting, discounts
data/catalog.js the demo catalogue (mock mode only)
store/ cart, wishlist, auth, toasts
components/ ui/ product/ cart/ layout/ shop/
pages/ one file per route
Re-skinning is one block: the CSS custom properties at the top of
src/index.css. Every component reads tokens, never literals, so changing the
palette changes the whole store.
A live store runs on Odoo 19 with the LOOM Storefront app from the Odoo App Store (search for "LOOM Storefront"
on apps.odoo.com). Odoo is the back office: products, prices, stock, orders, payments, customers, content and emails
stay there, and this storefront is the shop on its own domain. In Odoo, Storefront › Configuration › Set up a store
gives the values to put in VITE_API_BASE_URL, SITE_URL and LOOM_WEBHOOK_SECRET. The app needs Odoo.sh or your own
Odoo server; it cannot be installed on Odoo Online.
npm run build # → dist/ (files) and server-build/ (the render handler's bundle)
npm start # the Node server: dist/ plus pages rendered on request
A live store renders each page when it is asked for (server/handler.mjs), so a product added in Odoo after the
build is a real page for crawlers: its own title, description, Open Graph tags and structured data, a 404 for an
address that is nothing, a 301 for a changed slug, and robots.txt and the sitemap from Odoo. Adapters are in the
repository for Vercel (vercel.json, api/render.js), Netlify (netlify.toml,
netlify/functions/render.mjs), Cloudflare Pages (functions/[[path]].js) and any Node host or Docker
(server/node.mjs, Dockerfile). Step by step, with the environment variables: docs/DEPLOY.md.
The demo is written out as files at build time and runs on any static host. Set the site URL, or its canonical tags
point at a placeholder: SITE_URL=https://yourshop.com npm run build (Vercel's VERCEL_PROJECT_PRODUCTION_URL is
picked up on its own). vercel.json sets cleanUrls so /product/x finds product/x.html; public/_redirects does
the same on Netlify and Cloudflare Pages; with nginx, try_files $uri $uri.html $uri/ /index.html;.
Do not add a catch-all rewrite to
/above those. It serves the home page for every address. It looks correct in a browser, which routes around it, and is invisible until you check what a crawler actually received.
MIT. No attribution required, though a link back is appreciated.
| Bootstrap, caching, pagination, webhooks, scale |
| USER-GUIDE.md | For whoever runs the shop — ten tasks, one screen each |
| DATABASE.md | PostgreSQL schema for running your own backend |
| ERRORS.md | Error codes and a debugging checklist |
| TESTING.md | The suite, what it covers, and what it deliberately does not |
| INTEGRATION-PROMPT.md | Copy-paste prompt that has an AI build your backend |
| SCHEMA-PROMPT.md | Copy-paste prompt that has an AI design your database |