create-brainerce-store 1.51.0 → 1.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -0
- package/dist/index.js +24 -80
- package/messages/en.json +32 -0
- package/messages/he.json +32 -0
- package/package.json +1 -1
- package/templates/nextjs/base/.claude/commands/design.md +9 -0
- package/templates/nextjs/base/AI-GUIDE.md +52 -3
- package/templates/nextjs/base/CLAUDE.md +10 -0
- package/templates/nextjs/base/package.json.ejs +52 -39
- package/templates/nextjs/base/src/app/globals.css +36 -30
- package/templates/nextjs/base/src/components/checkout/payment-step.tsx +14 -10
- package/templates/nextjs/base/src/components/ui/accordion.tsx +53 -0
- package/templates/nextjs/base/src/components/ui/badge.tsx +32 -0
- package/templates/nextjs/base/src/components/ui/button.tsx +49 -0
- package/templates/nextjs/base/src/components/ui/card.tsx +55 -0
- package/templates/nextjs/base/src/components/ui/checkbox.tsx +28 -0
- package/templates/nextjs/base/src/components/ui/dialog.tsx +107 -0
- package/templates/nextjs/base/src/components/ui/input.tsx +22 -0
- package/templates/nextjs/base/src/components/ui/label.tsx +21 -0
- package/templates/nextjs/base/src/components/ui/radio-group.tsx +38 -0
- package/templates/nextjs/base/src/components/ui/select.tsx +153 -0
- package/templates/nextjs/base/src/components/ui/separator.tsx +26 -0
- package/templates/nextjs/base/src/components/ui/sheet.tsx +125 -0
- package/templates/nextjs/base/src/components/ui/skeleton.tsx +7 -0
- package/templates/nextjs/base/src/components/ui/tabs.tsx +55 -0
- package/templates/nextjs/base/src/components/ui/textarea.tsx +21 -0
- package/templates/nextjs/base/src/components/ui/tooltip.tsx +32 -0
- package/templates/nextjs/base/src/ui/cart/cart-bundle-offer.tsx +17 -11
- package/templates/nextjs/base/src/ui/cart/cart-item.tsx +2 -8
- package/templates/nextjs/base/src/ui/cart/cart-nudges.tsx +28 -39
- package/templates/nextjs/base/src/ui/cart/cart-summary.tsx +3 -1
- package/templates/nextjs/base/src/ui/cart/cart-upgrade-banner.tsx +8 -23
- package/templates/nextjs/base/src/ui/cart/cart-view.tsx +18 -27
- package/templates/nextjs/base/src/ui/cart/coupon-input.tsx +10 -21
- package/templates/nextjs/base/src/ui/cart/free-shipping-bar.tsx +2 -3
- package/templates/nextjs/base/src/ui/cart/reservation-countdown.tsx +95 -103
- package/templates/nextjs/base/src/ui/home/hero-section.tsx +4 -6
- package/templates/nextjs/base/src/ui/layout/announcement-bar.tsx.ejs +116 -125
- package/templates/nextjs/base/src/ui/layout/faq-section.tsx.ejs +90 -103
- package/templates/nextjs/base/src/ui/layout/header-account.tsx +2 -17
- package/templates/nextjs/base/src/ui/layout/language-switcher.tsx.ejs +80 -70
- package/templates/nextjs/base/src/ui/layout/site-footer.tsx.ejs +144 -164
- package/templates/nextjs/base/src/ui/layout/site-header.tsx.ejs +152 -182
- package/templates/nextjs/base/src/ui/product/customization-fields.tsx +456 -444
- package/templates/nextjs/base/src/ui/product/discount-badge.tsx +18 -22
- package/templates/nextjs/base/src/ui/product/frequently-bought-together.tsx +15 -27
- package/templates/nextjs/base/src/ui/product/modifier-group-selector.tsx +206 -175
- package/templates/nextjs/base/src/ui/product/price-display.tsx +3 -2
- package/templates/nextjs/base/src/ui/product/product-card.tsx +238 -271
- package/templates/nextjs/base/src/ui/product/product-client-section.tsx +455 -470
- package/templates/nextjs/base/src/ui/product/product-listing.tsx +96 -79
- package/templates/nextjs/base/src/ui/product/recommendation-section.tsx +102 -107
- package/templates/nextjs/base/src/ui/product/review-form.tsx +44 -43
- package/templates/nextjs/{designs/passepartout → base/src}/ui/product/reviews-section.tsx.ejs +108 -96
- package/templates/nextjs/base/src/ui/product/stock-badge.tsx +61 -63
- package/templates/nextjs/base/tailwind.config.ts +69 -42
- package/templates/nextjs/designs/{passepartout → atelier}/app-overlay/layout.tsx.ejs +23 -25
- package/templates/nextjs/designs/atelier/globals.css +396 -0
- package/templates/nextjs/designs/atelier/messages-patch/en.json +99 -0
- package/templates/nextjs/designs/atelier/messages-patch/he.json +99 -0
- package/templates/nextjs/designs/{passepartout → atelier}/ui/cart/cart-bundle-offer.tsx +110 -111
- package/templates/nextjs/designs/atelier/ui/cart/cart-drawer.tsx +163 -0
- package/templates/nextjs/designs/atelier/ui/cart/cart-item.tsx +140 -0
- package/templates/nextjs/designs/atelier/ui/cart/cart-nudges.tsx +34 -0
- package/templates/nextjs/designs/atelier/ui/cart/cart-summary.tsx +107 -0
- package/templates/nextjs/designs/{passepartout → atelier}/ui/cart/cart-upgrade-banner.tsx +123 -141
- package/templates/nextjs/designs/atelier/ui/cart/cart-view.tsx +147 -0
- package/templates/nextjs/designs/atelier/ui/cart/coupon-input.tsx +142 -0
- package/templates/nextjs/designs/{passepartout → atelier}/ui/cart/free-shipping-bar.tsx +77 -62
- package/templates/nextjs/designs/{passepartout → atelier}/ui/cart/reservation-countdown.tsx +89 -103
- package/templates/nextjs/designs/atelier/ui/home/benefits-band.tsx +34 -0
- package/templates/nextjs/designs/atelier/ui/home/category-tiles.tsx +148 -0
- package/templates/nextjs/designs/atelier/ui/home/discount-banner-strip.tsx +27 -0
- package/templates/nextjs/designs/atelier/ui/home/editorial-band.tsx +73 -0
- package/templates/nextjs/designs/atelier/ui/home/featured-products-section.tsx +36 -0
- package/templates/nextjs/designs/atelier/ui/home/hero-section.tsx +148 -0
- package/templates/nextjs/designs/atelier/ui/home/home-client.tsx +54 -0
- package/templates/nextjs/designs/atelier/ui/home/newsletter-section.tsx +78 -0
- package/templates/nextjs/designs/atelier/ui/home/testimonials-band.tsx +46 -0
- package/templates/nextjs/designs/atelier/ui/layout/announcement-bar.tsx +118 -0
- package/templates/nextjs/designs/atelier/ui/layout/faq-section.tsx +96 -0
- package/templates/nextjs/designs/atelier/ui/layout/header-account.tsx +36 -0
- package/templates/nextjs/designs/atelier/ui/layout/header-cart.tsx +36 -0
- package/templates/nextjs/designs/atelier/ui/layout/language-switcher.tsx.ejs +137 -0
- package/templates/nextjs/designs/atelier/ui/layout/nav-url.ts +14 -0
- package/templates/nextjs/designs/atelier/ui/layout/rich-text-block.tsx +34 -0
- package/templates/nextjs/designs/atelier/ui/layout/site-footer.tsx.ejs +141 -0
- package/templates/nextjs/designs/atelier/ui/layout/site-header.tsx.ejs +138 -0
- package/templates/nextjs/designs/atelier/ui/product/customization-fields.tsx +466 -0
- package/templates/nextjs/designs/{passepartout → atelier}/ui/product/discount-badge.tsx +17 -22
- package/templates/nextjs/designs/{passepartout → atelier}/ui/product/frequently-bought-together.tsx +196 -205
- package/templates/nextjs/designs/atelier/ui/product/modifier-group-selector.tsx +193 -0
- package/templates/nextjs/designs/atelier/ui/product/price-display.tsx +69 -0
- package/templates/nextjs/designs/atelier/ui/product/product-card.tsx +260 -0
- package/templates/nextjs/designs/atelier/ui/product/product-client-section.tsx +471 -0
- package/templates/nextjs/designs/atelier/ui/product/product-grid.tsx +47 -0
- package/templates/nextjs/designs/atelier/ui/product/product-listing.tsx +260 -0
- package/templates/nextjs/designs/atelier/ui/product/recommendation-section.tsx +95 -0
- package/templates/nextjs/designs/{passepartout → atelier}/ui/product/review-form.tsx +267 -294
- package/templates/nextjs/designs/atelier/ui/product/reviews-section.tsx.ejs +148 -0
- package/templates/nextjs/designs/atelier/ui/product/stock-badge.tsx +66 -0
- package/templates/nextjs/designs/atelier/ui/product/variant-selector.tsx +206 -0
- package/templates/nextjs/designs/atelier/ui/shared/cdn-image.tsx +29 -0
- package/templates/nextjs/designs/{passepartout → atelier}/ui/shared/fly-to-cart.ts +86 -85
- package/templates/nextjs/designs/atelier/ui/shared/icons.tsx +269 -0
- package/templates/nextjs/designs/atelier/ui/shared/loading-spinner.tsx +64 -0
- package/templates/nextjs/designs/atelier/ui/shared/reveal.tsx +71 -0
- package/templates/nextjs/designs/atelier/ui/shared/select-menu.tsx +125 -0
- package/templates/nextjs/ui-canvas/cart/cart-bundle-offer.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/cart-item.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/cart-nudges.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/cart-summary.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/cart-upgrade-banner.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/cart-view.tsx +2 -2
- package/templates/nextjs/ui-canvas/cart/coupon-input.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/free-shipping-bar.tsx +2 -0
- package/templates/nextjs/ui-canvas/cart/reservation-countdown.tsx +2 -0
- package/templates/nextjs/ui-canvas/home/discount-banner-strip.tsx +1 -1
- package/templates/nextjs/ui-canvas/home/featured-products-section.tsx +1 -1
- package/templates/nextjs/ui-canvas/home/hero-section.tsx +1 -1
- package/templates/nextjs/ui-canvas/home/home-client.tsx +1 -1
- package/templates/nextjs/ui-canvas/layout/announcement-bar.tsx.ejs +1 -1
- package/templates/nextjs/ui-canvas/layout/faq-section.tsx.ejs +2 -2
- package/templates/nextjs/ui-canvas/layout/header-account.tsx +1 -1
- package/templates/nextjs/ui-canvas/layout/language-switcher.tsx.ejs +2 -0
- package/templates/nextjs/ui-canvas/layout/rich-text-block.tsx.ejs +2 -0
- package/templates/nextjs/ui-canvas/layout/site-footer.tsx.ejs +2 -2
- package/templates/nextjs/ui-canvas/layout/site-header.tsx.ejs +2 -2
- package/templates/nextjs/ui-canvas/product/customization-fields.tsx +2 -0
- package/templates/nextjs/ui-canvas/product/discount-badge.tsx +2 -0
- package/templates/nextjs/ui-canvas/product/frequently-bought-together.tsx +2 -0
- package/templates/nextjs/ui-canvas/product/modifier-group-selector.tsx +2 -0
- package/templates/nextjs/ui-canvas/product/price-display.tsx +2 -0
- package/templates/nextjs/ui-canvas/product/product-card.tsx +1 -1
- package/templates/nextjs/ui-canvas/product/product-client-section.tsx +1 -1
- package/templates/nextjs/ui-canvas/product/product-grid.tsx +1 -1
- package/templates/nextjs/ui-canvas/product/product-listing.tsx +1 -1
- package/templates/nextjs/ui-canvas/product/recommendation-section.tsx +4 -0
- package/templates/nextjs/ui-canvas/product/review-form.tsx +29 -32
- package/templates/nextjs/ui-canvas/product/{reviews-section.tsx → reviews-section.tsx.ejs} +26 -8
- package/templates/nextjs/ui-canvas/product/stock-badge.tsx +2 -0
- package/templates/nextjs/ui-canvas/product/variant-selector.tsx +2 -0
- package/templates/nextjs/ui-canvas/shared/cdn-image.tsx +2 -0
- package/templates/nextjs/ui-canvas/shared/loading-spinner.tsx +2 -0
- package/templates/nextjs/base/src/ui/product/reviews-section.tsx +0 -85
- package/templates/nextjs/designs/passepartout/globals.css +0 -412
- package/templates/nextjs/designs/passepartout/messages-patch/en.json +0 -87
- package/templates/nextjs/designs/passepartout/messages-patch/he.json +0 -87
- package/templates/nextjs/designs/passepartout/ui/cart/cart-nudges.tsx +0 -39
- package/templates/nextjs/designs/passepartout/ui/cart/cart-view.tsx +0 -149
- package/templates/nextjs/designs/passepartout/ui/home/home-client.tsx +0 -401
- package/templates/nextjs/designs/passepartout/ui/layout/announcement-bar.tsx +0 -139
- package/templates/nextjs/designs/passepartout/ui/layout/cart-link.tsx +0 -45
- package/templates/nextjs/designs/passepartout/ui/layout/faq-section.tsx +0 -103
- package/templates/nextjs/designs/passepartout/ui/layout/site-footer.tsx +0 -159
- package/templates/nextjs/designs/passepartout/ui/layout/site-header.tsx.ejs +0 -155
- package/templates/nextjs/designs/passepartout/ui/layout/trust-icons.tsx +0 -60
- package/templates/nextjs/designs/passepartout/ui/layout/whatsapp-button.tsx +0 -34
- package/templates/nextjs/designs/passepartout/ui/product/price-display.tsx +0 -111
- package/templates/nextjs/designs/passepartout/ui/product/product-card.tsx +0 -265
- package/templates/nextjs/designs/passepartout/ui/product/product-client-section.tsx +0 -667
- package/templates/nextjs/designs/passepartout/ui/product/product-grid.tsx +0 -35
- package/templates/nextjs/designs/passepartout/ui/product/product-listing.tsx +0 -427
- package/templates/nextjs/designs/passepartout/ui/product/recommendation-section.tsx +0 -113
- package/templates/nextjs/designs/passepartout/ui/product/stock-badge.tsx +0 -52
- package/templates/nextjs/designs/passepartout/ui/product/variant-selector.tsx +0 -307
- package/templates/nextjs/designs/passepartout/ui/shared/loading-spinner.tsx +0 -33
- package/templates/nextjs/themes/luxury/globals.css +0 -399
- package/templates/nextjs/themes/luxury/theme.json +0 -23
- package/templates/nextjs/themes/minimal/globals.css +0 -30
- package/templates/nextjs/themes/minimal/theme.json +0 -23
- package/templates/nextjs/themes/playful/globals.css +0 -400
- package/templates/nextjs/themes/playful/theme.json +0 -23
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# create-brainerce-store
|
|
2
|
+
|
|
3
|
+
Scaffold a production-ready e-commerce storefront connected to [Brainerce](https://brainerce.com) — cart, checkout, variants, coupons, auth, SEO, and i18n wired out of the box.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm create brainerce-store@latest my-store -- --connection-id vc_xxxxxxxx
|
|
7
|
+
# or
|
|
8
|
+
pnpm create brainerce-store my-store --connection-id vc_xxxxxxxx
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Run it with no flags for a fully interactive setup. The CLI fetches your store's name, currency, language, and locales from the connection ID (`vc_*`, from your Brainerce dashboard), so the generated store matches the real channel from the first `dev` run.
|
|
12
|
+
|
|
13
|
+
## The design
|
|
14
|
+
|
|
15
|
+
Every scaffold ships **Atelier** — a complete, AI-built storefront look (not just a color theme): warm editorial gallery with soft washes + glass surfaces, a floating hero collage, near-full-bleed product grid, styled popover dropdowns, a mini-cart drawer that opens on add-to-cart, and an RTL-safe fly-to-cart micro-interaction. Fully de-branded — driven by your store's name, catalog and dashboard content.
|
|
16
|
+
|
|
17
|
+
It's a starting point, not a lock-in: the entire look lives in `src/ui/` + `globals.css` and is designed to be rewritten (see below).
|
|
18
|
+
|
|
19
|
+
## Blank-canvas mode
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm create brainerce-store@latest my-store -- --connection-id vc_xxx --canvas
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`--canvas` ships `src/ui/` as bare, semantic, essentially-unstyled skeletons (`DESIGN ME` markers included) with zero aesthetic opinion — commerce stays fully wired. It's the starting point for designing a storefront from scratch with an AI session, and the authoring substrate for new gallery designs. Canvas mode skips the design pack entirely.
|
|
26
|
+
|
|
27
|
+
## AI-first by default
|
|
28
|
+
|
|
29
|
+
Every scaffolded store is ready to be redesigned by an AI coding session:
|
|
30
|
+
|
|
31
|
+
- **`CLAUDE.md`** — auto-loaded by Claude Code; teaches the session the one rule (`core/` is the platform's, `ui/` is yours) before it touches anything.
|
|
32
|
+
- **`AGENTS.md`** — the same context for other agentic tools.
|
|
33
|
+
- **`/design <your art-direction brief>`** — a ready-made slash command that walks the full redesign: concept → implementation in `ui/` → verification (tsc, real browser, screenshots, RTL checks).
|
|
34
|
+
- **`AI-GUIDE.md`** — the design contract: file map, per-page hook contracts, verification loop, and hard-won RTL/i18n gotchas from real agency builds.
|
|
35
|
+
|
|
36
|
+
## Architecture (core/ui)
|
|
37
|
+
|
|
38
|
+
- `src/core/` — platform-owned commerce: client, auth, providers, and data/behavior hooks that return state + handlers, never JSX. Don't modify.
|
|
39
|
+
- `src/ui/` — 100% replaceable presentation. Delete-and-rebuild is encouraged; the store keeps working.
|
|
40
|
+
- `src/app/` — thin routes composing the two (~10 lines each).
|
|
41
|
+
- An ESLint boundary rule enforces the split in both directions.
|
|
42
|
+
|
|
43
|
+
Full details: [TEMPLATE-ARCHITECTURE.md](./TEMPLATE-ARCHITECTURE.md).
|
|
44
|
+
|
|
45
|
+
## Flags
|
|
46
|
+
|
|
47
|
+
| Flag | Description | Default |
|
|
48
|
+
| --- | --- | --- |
|
|
49
|
+
| `--connection-id <id>` | Brainerce vibe-coded connection ID (`vc_*`) | prompted |
|
|
50
|
+
| `--canvas` | Bare unstyled `src/ui/` skeletons for AI-driven design | off |
|
|
51
|
+
| `--language <lang>` | Store language (`en`, `he`) | fetched from store |
|
|
52
|
+
| `--pkg-manager <pm>` | `npm`, `pnpm`, `yarn`, `bun` | auto-detected |
|
|
53
|
+
| `--framework <fw>` | `nextjs` (Vite/Remix coming) | `nextjs` |
|
|
54
|
+
| `--api-url <url>` | Brainerce API base URL (or `BRAINERCE_API_URL` env) | auto-discovered |
|
|
55
|
+
| `--no-git` | Skip git initialization | git on |
|
|
56
|
+
| `--no-install` | Skip dependency installation | install on |
|
|
57
|
+
|
|
58
|
+
Pass `.` as the project name to scaffold into the current directory.
|
|
59
|
+
|
|
60
|
+
## Requirements
|
|
61
|
+
|
|
62
|
+
Node `^20.19.0 || ^22.13.0 || >=24.0.0`.
|
|
63
|
+
|
|
64
|
+
## After scaffolding
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd my-store
|
|
68
|
+
pnpm dev # store at http://localhost:3000
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Want a unique look? Open the folder in Claude Code and run `/design <your art-direction brief>`.
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "create-brainerce-store",
|
|
34
|
-
version: "1.
|
|
34
|
+
version: "1.52.1",
|
|
35
35
|
description: "Scaffold a production-ready e-commerce storefront connected to Brainerce",
|
|
36
36
|
bin: {
|
|
37
37
|
"create-brainerce-store": "dist/index.js"
|
|
@@ -288,37 +288,6 @@ async function runInteractive(defaults) {
|
|
|
288
288
|
initial: 0
|
|
289
289
|
});
|
|
290
290
|
}
|
|
291
|
-
questions.push({
|
|
292
|
-
type: "select",
|
|
293
|
-
name: "framework",
|
|
294
|
-
message: "Framework:",
|
|
295
|
-
choices: [
|
|
296
|
-
{ title: "Next.js 15 (recommended)", value: "nextjs" },
|
|
297
|
-
{ title: "Vite + React (coming soon)", value: "vite", disabled: true },
|
|
298
|
-
{ title: "Remix (coming soon)", value: "remix", disabled: true }
|
|
299
|
-
],
|
|
300
|
-
initial: 0
|
|
301
|
-
});
|
|
302
|
-
if (!defaults.canvas && !defaults.design) {
|
|
303
|
-
questions.push({
|
|
304
|
-
type: "select",
|
|
305
|
-
name: "design",
|
|
306
|
-
message: "Design:",
|
|
307
|
-
choices: [
|
|
308
|
-
{
|
|
309
|
-
title: "Passe-Partout \u2014 warm gallery minimal (recommended)",
|
|
310
|
-
description: "Framed product cards, placard PDP, print-serif titles",
|
|
311
|
-
value: "passepartout"
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
title: "Minimal \u2014 bare clean base",
|
|
315
|
-
description: "Neutral tokens, unopinionated layout",
|
|
316
|
-
value: "minimal"
|
|
317
|
-
}
|
|
318
|
-
],
|
|
319
|
-
initial: 0
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
291
|
questions.push({
|
|
323
292
|
type: "select",
|
|
324
293
|
name: "pkgManager",
|
|
@@ -352,9 +321,8 @@ async function runInteractive(defaults) {
|
|
|
352
321
|
projectName: defaults.projectName || response.projectName,
|
|
353
322
|
connectionId: defaults.connectionId || response.connectionId,
|
|
354
323
|
language: response.language || defaults.language || "en",
|
|
355
|
-
framework:
|
|
356
|
-
|
|
357
|
-
design: response.design || defaults.design || "minimal",
|
|
324
|
+
framework: defaults.framework || "nextjs",
|
|
325
|
+
design: response.design || defaults.design || "atelier",
|
|
358
326
|
pkgManager: response.pkgManager || defaults.pkgManager || detectInvokingPackageManager()
|
|
359
327
|
};
|
|
360
328
|
}
|
|
@@ -381,22 +349,8 @@ function toEnvLiteral(value) {
|
|
|
381
349
|
function isValidLocale(locale) {
|
|
382
350
|
return typeof locale === "string" && /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})?$/.test(locale);
|
|
383
351
|
}
|
|
384
|
-
function getFontConfig(language
|
|
352
|
+
function getFontConfig(language) {
|
|
385
353
|
const isHebrew = language === "he";
|
|
386
|
-
if (theme === "luxury") {
|
|
387
|
-
const subsets = isHebrew ? "['latin']" : "['latin']";
|
|
388
|
-
return {
|
|
389
|
-
fontImport: "import { Cormorant_Garamond } from 'next/font/google';",
|
|
390
|
-
fontVariable: `const font = Cormorant_Garamond({ weight: ['400', '500', '600', '700'], subsets: ${subsets} });`
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
if (theme === "playful") {
|
|
394
|
-
const subsets = isHebrew ? "['latin']" : "['latin']";
|
|
395
|
-
return {
|
|
396
|
-
fontImport: "import { Nunito } from 'next/font/google';",
|
|
397
|
-
fontVariable: `const font = Nunito({ subsets: ${subsets} });`
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
354
|
if (isHebrew) {
|
|
401
355
|
return {
|
|
402
356
|
fontImport: "import { Rubik } from 'next/font/google';",
|
|
@@ -409,7 +363,7 @@ function getFontConfig(language, theme) {
|
|
|
409
363
|
};
|
|
410
364
|
}
|
|
411
365
|
async function scaffold(options) {
|
|
412
|
-
const { projectName, framework,
|
|
366
|
+
const { projectName, framework, scaffoldInPlace } = options;
|
|
413
367
|
const targetDir = scaffoldInPlace ? process.cwd() : import_path.default.resolve(process.cwd(), projectName);
|
|
414
368
|
if (!scaffoldInPlace && await import_fs_extra.default.pathExists(targetDir)) {
|
|
415
369
|
const contents = await import_fs_extra.default.readdir(targetDir);
|
|
@@ -419,12 +373,11 @@ async function scaffold(options) {
|
|
|
419
373
|
}
|
|
420
374
|
const templatesRoot = findTemplatesDir(__dirname);
|
|
421
375
|
const baseDir = import_path.default.join(templatesRoot, framework, "base");
|
|
422
|
-
const themeDir = import_path.default.join(templatesRoot, framework, "themes", theme);
|
|
423
376
|
if (!await import_fs_extra.default.pathExists(baseDir)) {
|
|
424
377
|
throw new Error(`Template "${framework}" not found at ${baseDir}`);
|
|
425
378
|
}
|
|
426
379
|
const direction = getDirection(options.language);
|
|
427
|
-
const fontConfig = getFontConfig(options.language
|
|
380
|
+
const fontConfig = getFontConfig(options.language);
|
|
428
381
|
const ogLocale = options.language === "he" ? "he_IL" : "en_US";
|
|
429
382
|
const rawSupportedLocales = options.i18n?.supportedLocales || [options.language];
|
|
430
383
|
const supportedLocales = rawSupportedLocales.filter(isValidLocale);
|
|
@@ -537,16 +490,6 @@ async function scaffold(options) {
|
|
|
537
490
|
await import_fs_extra.default.move(import_path.default.join(appDir, entry.name), import_path.default.join(localeDir, entry.name));
|
|
538
491
|
}
|
|
539
492
|
}
|
|
540
|
-
if (!options.canvas && !designName && await import_fs_extra.default.pathExists(themeDir)) {
|
|
541
|
-
const themeCss = import_path.default.join(themeDir, "globals.css");
|
|
542
|
-
if (await import_fs_extra.default.pathExists(themeCss)) {
|
|
543
|
-
await import_fs_extra.default.copy(themeCss, import_path.default.join(targetDir, "src", "app", "globals.css"));
|
|
544
|
-
}
|
|
545
|
-
const themeJson = import_path.default.join(themeDir, "theme.json");
|
|
546
|
-
if (await import_fs_extra.default.pathExists(themeJson)) {
|
|
547
|
-
await import_fs_extra.default.copy(themeJson, import_path.default.join(targetDir, "theme.json"));
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
493
|
}
|
|
551
494
|
function deepMerge(base, patch) {
|
|
552
495
|
const out = { ...base };
|
|
@@ -777,10 +720,7 @@ var program = new import_commander.Command();
|
|
|
777
720
|
program.name("create-brainerce-store").description("Scaffold a production-ready e-commerce storefront connected to Brainerce").version(pkg.version).argument("[project-name]", "Name for the project directory").option("--connection-id <id>", "Brainerce vibe-coded connection ID (vc_*)").option(
|
|
778
721
|
"--api-url <url>",
|
|
779
722
|
"Brainerce API base URL (overrides BRAINERCE_API_URL env, defaults to https://api.brainerce.com)"
|
|
780
|
-
).option("--language <lang>", "Store language (en, he)").
|
|
781
|
-
"--design <design>",
|
|
782
|
-
"Storefront design pack: passepartout (warm gallery minimal) or minimal (bare base)"
|
|
783
|
-
).option("--pkg-manager <manager>", "Package manager (npm, pnpm, yarn, bun)").option(
|
|
723
|
+
).option("--language <lang>", "Store language (en, he)").addOption(new import_commander.Option("--framework <framework>", "Framework to use").default("nextjs").hideHelp()).addOption(new import_commander.Option("--design <design>", "Storefront design pack").hideHelp()).option("--pkg-manager <manager>", "Package manager (npm, pnpm, yarn, bun)").option(
|
|
784
724
|
"--canvas",
|
|
785
725
|
"Scaffold src/ui as bare unstyled skeletons \u2014 a blank canvas for AI-driven design (commerce stays fully wired)"
|
|
786
726
|
).option("--no-git", "Skip git initialization").option("--no-install", "Skip dependency installation").action(async (projectNameArg, options) => {
|
|
@@ -814,8 +754,7 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
814
754
|
const VALID_LANGUAGES = ["en", "he"];
|
|
815
755
|
const VALID_PKG_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
|
|
816
756
|
const VALID_FRAMEWORKS = ["nextjs"];
|
|
817
|
-
const
|
|
818
|
-
const VALID_DESIGNS = ["minimal", "passepartout"];
|
|
757
|
+
const VALID_DESIGNS = ["minimal", "atelier"];
|
|
819
758
|
let language = options.language;
|
|
820
759
|
if (language && !VALID_LANGUAGES.includes(language)) {
|
|
821
760
|
logger.error(
|
|
@@ -830,11 +769,6 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
830
769
|
);
|
|
831
770
|
process.exit(1);
|
|
832
771
|
}
|
|
833
|
-
let theme = options.theme;
|
|
834
|
-
if (!VALID_THEMES.includes(theme)) {
|
|
835
|
-
logger.error(`Invalid --theme "${theme}". Expected one of: ${VALID_THEMES.join(", ")}`);
|
|
836
|
-
process.exit(1);
|
|
837
|
-
}
|
|
838
772
|
let design = options.design;
|
|
839
773
|
if (design && !VALID_DESIGNS.includes(design)) {
|
|
840
774
|
logger.error(`Invalid --design "${design}". Expected one of: ${VALID_DESIGNS.join(", ")}`);
|
|
@@ -888,7 +822,6 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
888
822
|
connectionId,
|
|
889
823
|
language: languageDefault,
|
|
890
824
|
framework,
|
|
891
|
-
theme,
|
|
892
825
|
design,
|
|
893
826
|
pkgManager,
|
|
894
827
|
canvas
|
|
@@ -897,7 +830,6 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
897
830
|
connectionId = answers.connectionId;
|
|
898
831
|
language = answers.language;
|
|
899
832
|
framework = answers.framework;
|
|
900
|
-
theme = answers.theme;
|
|
901
833
|
design = answers.design;
|
|
902
834
|
pkgManager = answers.pkgManager;
|
|
903
835
|
}
|
|
@@ -945,14 +877,13 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
945
877
|
connectionId,
|
|
946
878
|
apiBaseUrl: resolvedApiUrl,
|
|
947
879
|
framework,
|
|
948
|
-
theme,
|
|
949
880
|
storeName: storeInfo.name,
|
|
950
881
|
currency: storeInfo.currency,
|
|
951
882
|
language: language || storeInfo.language,
|
|
952
883
|
i18n: storeInfo.i18n,
|
|
953
884
|
scaffoldInPlace,
|
|
954
885
|
canvas,
|
|
955
|
-
design: canvas ? void 0 : design || "
|
|
886
|
+
design: canvas ? void 0 : design || "atelier"
|
|
956
887
|
});
|
|
957
888
|
scaffoldSpinner.succeed(
|
|
958
889
|
scaffoldInPlace ? "Scaffolded into current directory" : `Scaffolded into ./${projectName}`
|
|
@@ -966,9 +897,16 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
966
897
|
const gitOpts = { cwd, stdio: ["ignore", "ignore", "pipe"] };
|
|
967
898
|
execFileSync("git", ["init"], gitOpts);
|
|
968
899
|
execFileSync("git", ["add", "-A"], gitOpts);
|
|
900
|
+
let hasIdentity = true;
|
|
901
|
+
try {
|
|
902
|
+
execFileSync("git", ["config", "user.email"], gitOpts);
|
|
903
|
+
} catch {
|
|
904
|
+
hasIdentity = false;
|
|
905
|
+
}
|
|
906
|
+
const identityArgs = hasIdentity ? [] : ["-c", "user.name=Brainerce", "-c", "user.email=scaffold@brainerce.com"];
|
|
969
907
|
execFileSync(
|
|
970
908
|
"git",
|
|
971
|
-
["commit", "-m", "Initial commit from create-brainerce-store"],
|
|
909
|
+
[...identityArgs, "commit", "-m", "Initial commit from create-brainerce-store"],
|
|
972
910
|
gitOpts
|
|
973
911
|
);
|
|
974
912
|
gitSpinner.succeed("Git initialized");
|
|
@@ -981,8 +919,14 @@ program.name("create-brainerce-store").description("Scaffold a production-ready
|
|
|
981
919
|
if (!skipInstall) {
|
|
982
920
|
const installSpinner = createSpinner(`Installing dependencies with ${pkgManager}...`);
|
|
983
921
|
installSpinner.start();
|
|
922
|
+
const installDir = scaffoldInPlace ? "." : projectName;
|
|
984
923
|
try {
|
|
985
|
-
|
|
924
|
+
const installArgs = pkgManager === "pnpm" ? ["--ignore-workspace"] : [];
|
|
925
|
+
await installDependencies(installDir, pkgManager, { args: installArgs });
|
|
926
|
+
const fsExtra = require("fs-extra");
|
|
927
|
+
if (!await fsExtra.pathExists(import_path2.default.join(installDir, "node_modules"))) {
|
|
928
|
+
throw new Error("Install completed but node_modules was not created.");
|
|
929
|
+
}
|
|
986
930
|
installSpinner.succeed("Dependencies installed");
|
|
987
931
|
} catch (err) {
|
|
988
932
|
installSpinner.fail("Dependency installation failed");
|
package/messages/en.json
CHANGED
|
@@ -100,6 +100,38 @@
|
|
|
100
100
|
"addingAll": "Adding...",
|
|
101
101
|
"by": "By"
|
|
102
102
|
},
|
|
103
|
+
"reviews": {
|
|
104
|
+
"title": "Reviews",
|
|
105
|
+
"noReviews": "No reviews yet — be the first to share your experience.",
|
|
106
|
+
"verifiedPurchase": "Verified purchase",
|
|
107
|
+
"loading": "Loading…",
|
|
108
|
+
"signIn": "Sign in",
|
|
109
|
+
"signInSuffix": "to leave a review for this product.",
|
|
110
|
+
"onlyPurchasers": "Only customers who purchased this product can leave a review.",
|
|
111
|
+
"reviewsDisabled": "Reviews are not enabled for this store.",
|
|
112
|
+
"cannotReview": "You cannot review this product right now.",
|
|
113
|
+
"confirmDelete": "Delete your review for this product?",
|
|
114
|
+
"deleteFailed": "Could not delete your review. Please try again.",
|
|
115
|
+
"startOver": "Want to start over? You can delete your review.",
|
|
116
|
+
"deleting": "Deleting…",
|
|
117
|
+
"deleteReview": "Delete review",
|
|
118
|
+
"alreadySubmitted": "You've already submitted a review for this product.",
|
|
119
|
+
"tooMany": "Too many submissions. Please try again in a few minutes.",
|
|
120
|
+
"updateFailed": "Could not update your review. Please try again.",
|
|
121
|
+
"submitFailed": "Could not submit your review. Please try again.",
|
|
122
|
+
"thanksUpdated": "Thanks! Your review has been updated.",
|
|
123
|
+
"thanksSubmitted": "Thanks! Your review has been submitted.",
|
|
124
|
+
"editYourReview": "Edit your review",
|
|
125
|
+
"writeReview": "Write a review",
|
|
126
|
+
"yourRating": "Your rating",
|
|
127
|
+
"starRating": "Star rating",
|
|
128
|
+
"yourReview": "Your review",
|
|
129
|
+
"optionalField": "optional",
|
|
130
|
+
"saving": "Saving…",
|
|
131
|
+
"submittingBtn": "Submitting…",
|
|
132
|
+
"saveChanges": "Save changes",
|
|
133
|
+
"submitReview": "Submit review"
|
|
134
|
+
},
|
|
103
135
|
"customization": {
|
|
104
136
|
"title": "Personalize this product",
|
|
105
137
|
"selectPlaceholder": "Choose an option",
|
package/messages/he.json
CHANGED
|
@@ -100,6 +100,38 @@
|
|
|
100
100
|
"addingAll": "מוסיף...",
|
|
101
101
|
"by": "מאת"
|
|
102
102
|
},
|
|
103
|
+
"reviews": {
|
|
104
|
+
"title": "ביקורות",
|
|
105
|
+
"noReviews": "אין עדיין ביקורות — היו הראשונים לשתף.",
|
|
106
|
+
"verifiedPurchase": "רכישה מאומתת",
|
|
107
|
+
"loading": "טוען…",
|
|
108
|
+
"signIn": "התחברו",
|
|
109
|
+
"signInSuffix": "כדי לכתוב ביקורת על המוצר.",
|
|
110
|
+
"onlyPurchasers": "רק לקוחות שרכשו את המוצר יכולים לכתוב ביקורת.",
|
|
111
|
+
"reviewsDisabled": "ביקורות אינן פעילות בחנות זו.",
|
|
112
|
+
"cannotReview": "לא ניתן לכתוב ביקורת על המוצר כרגע.",
|
|
113
|
+
"confirmDelete": "למחוק את הביקורת שלך על המוצר?",
|
|
114
|
+
"deleteFailed": "לא ניתן היה למחוק את הביקורת. נסו שוב.",
|
|
115
|
+
"startOver": "רוצים להתחיל מחדש? אפשר למחוק את הביקורת.",
|
|
116
|
+
"deleting": "מוחק…",
|
|
117
|
+
"deleteReview": "מחיקת ביקורת",
|
|
118
|
+
"alreadySubmitted": "כבר שלחתם ביקורת על המוצר הזה.",
|
|
119
|
+
"tooMany": "יותר מדי נסיונות. נסו שוב בעוד כמה דקות.",
|
|
120
|
+
"updateFailed": "לא ניתן היה לעדכן את הביקורת. נסו שוב.",
|
|
121
|
+
"submitFailed": "לא ניתן היה לשלוח את הביקורת. נסו שוב.",
|
|
122
|
+
"thanksUpdated": "תודה! הביקורת עודכנה.",
|
|
123
|
+
"thanksSubmitted": "תודה! הביקורת נשלחה.",
|
|
124
|
+
"editYourReview": "עריכת הביקורת",
|
|
125
|
+
"writeReview": "כתיבת ביקורת",
|
|
126
|
+
"yourRating": "הדירוג שלכם",
|
|
127
|
+
"starRating": "דירוג כוכבים",
|
|
128
|
+
"yourReview": "הביקורת שלכם",
|
|
129
|
+
"optionalField": "לא חובה",
|
|
130
|
+
"saving": "שומר…",
|
|
131
|
+
"submittingBtn": "שולח…",
|
|
132
|
+
"saveChanges": "שמירת שינויים",
|
|
133
|
+
"submitReview": "שליחת ביקורת"
|
|
134
|
+
},
|
|
103
135
|
"customization": {
|
|
104
136
|
"title": "התאמה אישית של המוצר",
|
|
105
137
|
"selectPlaceholder": "בחר אפשרות",
|
package/package.json
CHANGED
|
@@ -32,6 +32,15 @@ which surface.
|
|
|
32
32
|
|
|
33
33
|
## The process
|
|
34
34
|
|
|
35
|
+
## The quality bar (non-negotiable — from the AI-GUIDE)
|
|
36
|
+
|
|
37
|
+
Exactly 3-5 colors (no purple unless asked, no gradients by default), max 2
|
|
38
|
+
font families, tokens-only colors, Tailwind spacing scale, real imagery
|
|
39
|
+
(never abstract filler), content-rich sections, mobile-first. After EACH
|
|
40
|
+
major surface: screenshot → self-critique ("would a Lovable user accept
|
|
41
|
+
this?") → fix → continue. See AI-GUIDE.md "The quality bar".
|
|
42
|
+
|
|
43
|
+
|
|
35
44
|
1. **Commit to ONE art direction** — write it down in 4 lines (typography
|
|
36
45
|
pairing incl. a script-compatible webfont, 6-10 color tokens, layout
|
|
37
46
|
concept, motion language) at the top of `DESIGN.md` in the project root.
|
|
@@ -26,10 +26,31 @@ core change, stop and say so instead.
|
|
|
26
26
|
| `src/ui/cart/` | you | cart page pieces |
|
|
27
27
|
| `src/ui/shared/` | you | loader, image wrapper |
|
|
28
28
|
| `src/app/globals.css` | you | tokens + global styles |
|
|
29
|
+
| `src/components/ui/` | shared | shadcn/ui primitives — compose them, extend via variants |
|
|
29
30
|
| `src/core/**` | platform | hooks, lib, providers — read, never edit |
|
|
30
31
|
| `src/components/{checkout,auth,account,seo}` | platform | core-styled in v1; they inherit your tokens |
|
|
31
32
|
| `src/app/**` | platform | thin routes; edit only to wire new ui components |
|
|
32
33
|
|
|
34
|
+
## The dialect (shadcn/ui + lucide + cn)
|
|
35
|
+
|
|
36
|
+
This store speaks the same component dialect as Lovable / v0 / Bolt output:
|
|
37
|
+
|
|
38
|
+
- **`src/components/ui/` holds official shadcn/ui primitives** (button, card,
|
|
39
|
+
badge, input, label, textarea, select, checkbox, radio-group, separator,
|
|
40
|
+
accordion, dialog, sheet, skeleton, tabs, tooltip). Compose them in `src/ui/`
|
|
41
|
+
instead of hand-rolling controls. Need a new look? **Extend via CVA
|
|
42
|
+
variants** (add a variant to `buttonVariants`/`badgeVariants`), never by
|
|
43
|
+
inline-overriding the same styles in twenty call sites.
|
|
44
|
+
- **Icons: lucide-react only.** No inline `<svg>` paths, no emoji-as-icons,
|
|
45
|
+
no second icon set. Consistent 16/20/24px sizes.
|
|
46
|
+
- **Class merging: `cn()`** from `@/core/lib/utils` (clsx + tailwind-merge) —
|
|
47
|
+
it's the same helper shadcn expects, already wired into every primitive.
|
|
48
|
+
- **Tokens drive everything**: primitives read `--primary`, `--card`,
|
|
49
|
+
`--input`, `--ring`, `--radius`, etc. from `globals.css`. Restyle the store
|
|
50
|
+
by changing tokens (and variants), not by scattering literal colors.
|
|
51
|
+
- `rounded`, `rounded-md`, `rounded-lg` all derive from `--radius`
|
|
52
|
+
(shadcn convention), so corner radius follows the theme automatically.
|
|
53
|
+
|
|
33
54
|
## The hook contract (your data supply)
|
|
34
55
|
|
|
35
56
|
UI components get *everything* from `@/core/hooks/*` and
|
|
@@ -54,6 +75,34 @@ images, stock) comes from them — **never hardcode products**.
|
|
|
54
75
|
4. If the store is RTL: check nothing is left-anchored that should be
|
|
55
76
|
right-anchored, and directional arrows point with the reading direction.
|
|
56
77
|
|
|
78
|
+
## The quality bar (distilled from Lovable / v0 / Bolt system prompts)
|
|
79
|
+
|
|
80
|
+
Beautiful is the top priority — the first render must wow. Hard rules:
|
|
81
|
+
|
|
82
|
+
1. **Design system first**: define all HSL semantic tokens in globals.css
|
|
83
|
+
BEFORE styling any component. Never direct colors (`text-white`,
|
|
84
|
+
`bg-black`) in classNames — tokens only.
|
|
85
|
+
2. **Color budget: exactly 3-5 colors.** 1 brand color, 2-3 neutrals, 1-2
|
|
86
|
+
accents. Never purple/violet unless the merchant asked. No gradients by
|
|
87
|
+
default — solid colors; gradients only as subtle accents if requested.
|
|
88
|
+
3. **Max 2 font families** (1 display + 1 body, both with the store's
|
|
89
|
+
script). Body line-height 1.4-1.6. Nothing below 14px.
|
|
90
|
+
4. **Mobile-first**; flexbox by default, grid for true 2D; no absolute
|
|
91
|
+
positioning unless necessary.
|
|
92
|
+
5. **Tailwind discipline**: spacing scale only (`p-4`, never `p-[16px]`),
|
|
93
|
+
`gap-*` over margins between siblings, `text-balance` on headlines.
|
|
94
|
+
6. **Real imagery everywhere** — product photos from the catalog do the
|
|
95
|
+
heavy lifting; free stock hotlinks (Pexels/Unsplash) for editorial
|
|
96
|
+
sections. NEVER abstract filler shapes (gradient circles, blobs).
|
|
97
|
+
NEVER emojis as icons — one icon set, consistent 16/20/24px sizes.
|
|
98
|
+
7. **Content-rich**: no section may render empty or thin. Empty states are
|
|
99
|
+
designed states with copy and structure, not blank space.
|
|
100
|
+
8. Component variants in the design system, not inline overrides.
|
|
101
|
+
9. Semantic HTML + ARIA + alt text + `sr-only` labels — always.
|
|
102
|
+
10. **Verify with your eyes**: screenshot after each major surface, critique
|
|
103
|
+
it ("would a Lovable user accept this?"), fix, and only then move on.
|
|
104
|
+
|
|
105
|
+
|
|
57
106
|
## Hard-won gotchas (each one cost a real debugging session)
|
|
58
107
|
|
|
59
108
|
- **RTL + cloned images**: `next/image` renders its `<img>` with `inset: 0`.
|
|
@@ -62,9 +111,9 @@ images, stock) comes from them — **never hardcode products**.
|
|
|
62
111
|
Set `inset: 'auto'` before positioning.
|
|
63
112
|
- **Never name a custom class `overline`** — it is a Tailwind utility
|
|
64
113
|
(`text-decoration-line: overline`) and will draw a line above your text.
|
|
65
|
-
- **`rounded-md` / `rounded-lg`
|
|
66
|
-
|
|
67
|
-
|
|
114
|
+
- **`rounded` / `rounded-md` / `rounded-lg` all follow `--radius`** (shadcn
|
|
115
|
+
convention, wired in tailwind.config.ts) — change the token, not the
|
|
116
|
+
classes, when you want sharper or softer corners.
|
|
68
117
|
- **Hebrew has no uppercase** — remove `text-transform: uppercase` and wide
|
|
69
118
|
`letter-spacing` from heading styles; they are Latin idioms that distort
|
|
70
119
|
Hebrew (tracking is acceptable only at caption sizes).
|
|
@@ -21,6 +21,16 @@ and handlers, never JSX. Never hardcode catalog content.
|
|
|
21
21
|
contracts, and hard-won RTL/i18n gotchas that will save you real debugging
|
|
22
22
|
time.
|
|
23
23
|
|
|
24
|
+
## The dialect
|
|
25
|
+
|
|
26
|
+
- `src/components/ui/` = official **shadcn/ui primitives** (Button, Card,
|
|
27
|
+
Badge, Input, Select, Accordion, Dialog, Sheet, Skeleton, …). Compose them;
|
|
28
|
+
extend looks via CVA **variants**, never repeated inline overrides.
|
|
29
|
+
- Icons: **lucide-react only** — no inline `<svg>`, no emoji-as-icons.
|
|
30
|
+
- Class merging: **`cn()`** from `@/core/lib/utils`.
|
|
31
|
+
- Colors/radius come from the semantic HSL tokens in `globals.css`
|
|
32
|
+
(`--primary`, `--card`, `--ring`, `--radius`, …) — restyle via tokens.
|
|
33
|
+
|
|
24
34
|
## Redesigning? Use the ready-made flow
|
|
25
35
|
|
|
26
36
|
Run `/design <your art-direction brief>` — it walks the whole process:
|
|
@@ -1,39 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "<%= projectName %>",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"dev": "next dev",
|
|
7
|
-
"build": "next build",
|
|
8
|
-
"start": "next start",
|
|
9
|
-
"lint": "next lint",
|
|
10
|
-
"setup": "node scripts/fetch-store-info.mjs"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"brainerce": "<%= brainerceVersion %>",
|
|
14
|
-
"next": "^15.3.4",
|
|
15
|
-
"react": "^19.0.0",
|
|
16
|
-
"react-dom": "^19.0.0",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"@
|
|
24
|
-
"@
|
|
25
|
-
"@
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= projectName %>",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint",
|
|
10
|
+
"setup": "node scripts/fetch-store-info.mjs"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"brainerce": "<%= brainerceVersion %>",
|
|
14
|
+
"next": "^15.3.4",
|
|
15
|
+
"react": "^19.0.0",
|
|
16
|
+
"react-dom": "^19.0.0",
|
|
17
|
+
"@radix-ui/react-accordion": "^1.2.0",
|
|
18
|
+
"@radix-ui/react-checkbox": "^1.1.1",
|
|
19
|
+
"@radix-ui/react-dialog": "^1.1.2",
|
|
20
|
+
"@radix-ui/react-label": "^2.1.0",
|
|
21
|
+
"@radix-ui/react-radio-group": "^1.2.0",
|
|
22
|
+
"@radix-ui/react-select": "^2.1.1",
|
|
23
|
+
"@radix-ui/react-separator": "^1.1.0",
|
|
24
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
25
|
+
"@radix-ui/react-tabs": "^1.1.0",
|
|
26
|
+
"@radix-ui/react-tooltip": "^1.1.4",
|
|
27
|
+
"class-variance-authority": "^0.7.1",
|
|
28
|
+
"clsx": "^2.1.1",
|
|
29
|
+
"lucide-react": "^0.462.0",
|
|
30
|
+
"tailwind-merge": "^2.5.2",
|
|
31
|
+
"tailwindcss-animate": "^1.0.7",
|
|
32
|
+
"isomorphic-dompurify": "<%= isomorphicDompurifyVersion %>",
|
|
33
|
+
"sharp": "^0.35.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.0.0",
|
|
37
|
+
"@types/react": "^19.0.0",
|
|
38
|
+
"@types/react-dom": "^19.0.0",
|
|
39
|
+
"autoprefixer": "^10.4.0",
|
|
40
|
+
"eslint": "^9.0.0",
|
|
41
|
+
"eslint-config-next": "^15.3.4",
|
|
42
|
+
"postcss": "^8.4.49",
|
|
43
|
+
"tailwindcss": "^3.4.0",
|
|
44
|
+
"typescript": "^5.4.0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": "^20.19.0 || ^22.13.0 || >=24.0.0"
|
|
48
|
+
},
|
|
49
|
+
"pnpm": {
|
|
50
|
+
"onlyBuiltDependencies": ["sharp"]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,30 +1,36 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@layer base {
|
|
6
|
-
:root {
|
|
7
|
-
--background: 0 0% 100%;
|
|
8
|
-
--foreground: 0 0% 9%;
|
|
9
|
-
--primary: 0 0% 9%;
|
|
10
|
-
--primary-foreground: 0 0% 98%;
|
|
11
|
-
--secondary: 0 0% 96%;
|
|
12
|
-
--secondary-foreground: 0 0% 9%;
|
|
13
|
-
--muted: 0 0% 96%;
|
|
14
|
-
--muted-foreground: 0 0% 45%;
|
|
15
|
-
--accent: 0 0% 96%;
|
|
16
|
-
--accent-foreground: 0 0% 9%;
|
|
17
|
-
--destructive: 0 84% 60%;
|
|
18
|
-
--destructive-foreground: 0 0% 98%;
|
|
19
|
-
--border: 0 0% 90%;
|
|
20
|
-
--
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer base {
|
|
6
|
+
:root {
|
|
7
|
+
--background: 0 0% 100%;
|
|
8
|
+
--foreground: 0 0% 9%;
|
|
9
|
+
--primary: 0 0% 9%;
|
|
10
|
+
--primary-foreground: 0 0% 98%;
|
|
11
|
+
--secondary: 0 0% 96%;
|
|
12
|
+
--secondary-foreground: 0 0% 9%;
|
|
13
|
+
--muted: 0 0% 96%;
|
|
14
|
+
--muted-foreground: 0 0% 45%;
|
|
15
|
+
--accent: 0 0% 96%;
|
|
16
|
+
--accent-foreground: 0 0% 9%;
|
|
17
|
+
--destructive: 0 84% 60%;
|
|
18
|
+
--destructive-foreground: 0 0% 98%;
|
|
19
|
+
--border: 0 0% 90%;
|
|
20
|
+
--input: 0 0% 90%;
|
|
21
|
+
--ring: 0 0% 9%;
|
|
22
|
+
--card: 0 0% 100%;
|
|
23
|
+
--card-foreground: 0 0% 9%;
|
|
24
|
+
--popover: 0 0% 100%;
|
|
25
|
+
--popover-foreground: 0 0% 9%;
|
|
26
|
+
--radius: 0.5rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
* {
|
|
30
|
+
@apply border-border;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
body {
|
|
34
|
+
@apply bg-background text-foreground antialiased;
|
|
35
|
+
}
|
|
36
|
+
}
|