@rovela-ai/sdk 0.19.3 → 0.19.5
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/dist/admin/server/admin-session.d.ts.map +1 -1
- package/dist/admin/server/admin-session.js +7 -0
- package/dist/admin/server/admin-session.js.map +1 -1
- package/dist/auth/server/customer-session.d.ts.map +1 -1
- package/dist/auth/server/customer-session.js +5 -0
- package/dist/auth/server/customer-session.js.map +1 -1
- package/dist/checkout/server/checkout-customer.d.ts.map +1 -1
- package/dist/checkout/server/checkout-customer.js +5 -0
- package/dist/checkout/server/checkout-customer.js.map +1 -1
- package/docs/changelog/README.md +53 -0
- package/docs/changelog/epoch-01-chrome-consent.md +63 -0
- package/docs/changelog/epoch-02-platform-commerce.md +108 -0
- package/docs/changelog/epoch-03-i18n-files.md +72 -0
- package/docs/changelog/epoch-04-emails.md +65 -0
- package/docs/changelog/epoch-05-admin-experience.md +98 -0
- package/docs/changelog/epoch-06-mobile-integrity.md +72 -0
- package/docs/design/admin-ledger-visual-universe.html +1961 -0
- package/docs/design/admin-sidebar-and-band.html +542 -0
- package/package.json +3 -1
- package/templates/store-template/.claude/skills/add-section/SKILL.md +438 -0
- package/templates/store-template/.claude/skills/build-feature/SKILL.md +201 -0
- package/templates/store-template/.claude/skills/customize-theme/SKILL.md +167 -0
- package/templates/store-template/.claude/skills/debug-errors/SKILL.md +68 -0
- package/templates/store-template/.claude/skills/frontend-design/SKILL.md +176 -0
- package/templates/store-template/.claude/skills/generate-images/SKILL.md +115 -0
- package/templates/store-template/.claude/skills/manage-products/SKILL.md +187 -0
- package/templates/store-template/.claude/skills/override-sdk-component/SKILL.md +154 -0
- package/templates/store-template/.env.example +50 -0
- package/templates/store-template/.mcp.json +8 -0
- package/templates/store-template/.rovela/blueprint.example.json +190 -0
- package/templates/store-template/CLAUDE.md +14 -0
- package/templates/store-template/app/LayoutContent.tsx +106 -0
- package/templates/store-template/app/[...path]/page.tsx +79 -0
- package/templates/store-template/app/account/addresses/page.tsx +45 -0
- package/templates/store-template/app/account/layout.tsx +17 -0
- package/templates/store-template/app/account/orders/[id]/invoice/page.tsx +277 -0
- package/templates/store-template/app/account/orders/[id]/page.tsx +725 -0
- package/templates/store-template/app/account/orders/page.tsx +153 -0
- package/templates/store-template/app/account/page.tsx +184 -0
- package/templates/store-template/app/account/profile/page.tsx +434 -0
- package/templates/store-template/app/admin/(dashboard)/account/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/events/page.tsx +14 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/layout.tsx +48 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/visitors/page.tsx +14 -0
- package/templates/store-template/app/admin/(dashboard)/categories/[id]/page.tsx +38 -0
- package/templates/store-template/app/admin/(dashboard)/categories/new/page.tsx +35 -0
- package/templates/store-template/app/admin/(dashboard)/categories/page.tsx +223 -0
- package/templates/store-template/app/admin/(dashboard)/customers/[id]/page.tsx +26 -0
- package/templates/store-template/app/admin/(dashboard)/customers/page.tsx +33 -0
- package/templates/store-template/app/admin/(dashboard)/discounts/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/emails/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/files/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/layout.tsx +44 -0
- package/templates/store-template/app/admin/(dashboard)/loading.tsx +88 -0
- package/templates/store-template/app/admin/(dashboard)/locations/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/orders/[id]/page.tsx +66 -0
- package/templates/store-template/app/admin/(dashboard)/orders/page.tsx +26 -0
- package/templates/store-template/app/admin/(dashboard)/page.tsx +146 -0
- package/templates/store-template/app/admin/(dashboard)/payments/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/products/[id]/page.tsx +38 -0
- package/templates/store-template/app/admin/(dashboard)/products/new/page.tsx +35 -0
- package/templates/store-template/app/admin/(dashboard)/products/page.tsx +31 -0
- package/templates/store-template/app/admin/(dashboard)/settings/page.tsx +46 -0
- package/templates/store-template/app/admin/(dashboard)/shipping/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/tax/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/users/[id]/page.tsx +114 -0
- package/templates/store-template/app/admin/(dashboard)/users/page.tsx +16 -0
- package/templates/store-template/app/admin/accept-invite/page.tsx +36 -0
- package/templates/store-template/app/admin/forgot-password/page.tsx +13 -0
- package/templates/store-template/app/admin/layout.tsx +47 -0
- package/templates/store-template/app/admin/login/page.tsx +528 -0
- package/templates/store-template/app/admin/reset-password/page.tsx +36 -0
- package/templates/store-template/app/api/account/addresses/[id]/route.ts +10 -0
- package/templates/store-template/app/api/account/addresses/route.ts +10 -0
- package/templates/store-template/app/api/account/change-password/route.ts +107 -0
- package/templates/store-template/app/api/account/orders/[id]/refund/route.ts +11 -0
- package/templates/store-template/app/api/account/orders/[id]/return/route.ts +14 -0
- package/templates/store-template/app/api/account/orders/[id]/route.ts +42 -0
- package/templates/store-template/app/api/account/orders/route.ts +29 -0
- package/templates/store-template/app/api/account/profile/route.ts +165 -0
- package/templates/store-template/app/api/admin/accept-invite/route.ts +11 -0
- package/templates/store-template/app/api/admin/analytics/events/route.ts +9 -0
- package/templates/store-template/app/api/admin/analytics/route.ts +10 -0
- package/templates/store-template/app/api/admin/analytics/visitors/route.ts +9 -0
- package/templates/store-template/app/api/admin/branding/favicon/route.ts +9 -0
- package/templates/store-template/app/api/admin/branding/logo/route.ts +9 -0
- package/templates/store-template/app/api/admin/categories/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/categories/route.ts +9 -0
- package/templates/store-template/app/api/admin/check/route.ts +10 -0
- package/templates/store-template/app/api/admin/customer-groups/[id]/route.ts +10 -0
- package/templates/store-template/app/api/admin/customer-groups/route.ts +10 -0
- package/templates/store-template/app/api/admin/customers/[id]/addresses/[addressId]/route.ts +15 -0
- package/templates/store-template/app/api/admin/customers/[id]/addresses/route.ts +15 -0
- package/templates/store-template/app/api/admin/customers/[id]/route.ts +11 -0
- package/templates/store-template/app/api/admin/customers/bulk/route.ts +8 -0
- package/templates/store-template/app/api/admin/customers/route.ts +9 -0
- package/templates/store-template/app/api/admin/discounts/[id]/route.ts +11 -0
- package/templates/store-template/app/api/admin/discounts/route.ts +10 -0
- package/templates/store-template/app/api/admin/emails/preview/route.ts +4 -0
- package/templates/store-template/app/api/admin/emails/route.ts +5 -0
- package/templates/store-template/app/api/admin/emails/test/route.ts +4 -0
- package/templates/store-template/app/api/admin/files/route.ts +8 -0
- package/templates/store-template/app/api/admin/forgot-password/route.ts +7 -0
- package/templates/store-template/app/api/admin/linked-customer/route.ts +11 -0
- package/templates/store-template/app/api/admin/locations/[id]/route.ts +10 -0
- package/templates/store-template/app/api/admin/locations/route.ts +10 -0
- package/templates/store-template/app/api/admin/me/password/route.ts +13 -0
- package/templates/store-template/app/api/admin/me/route.ts +11 -0
- package/templates/store-template/app/api/admin/orders/[id]/refund/route.ts +7 -0
- package/templates/store-template/app/api/admin/orders/[id]/return/approve/route.ts +7 -0
- package/templates/store-template/app/api/admin/orders/[id]/return/reject/route.ts +7 -0
- package/templates/store-template/app/api/admin/orders/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/orders/[id]/ship-with-shippo/route.ts +6 -0
- package/templates/store-template/app/api/admin/orders/[id]/shippo-rates/route.ts +6 -0
- package/templates/store-template/app/api/admin/orders/bulk/route.ts +8 -0
- package/templates/store-template/app/api/admin/orders/route.ts +9 -0
- package/templates/store-template/app/api/admin/payment-methods/[id]/route.ts +10 -0
- package/templates/store-template/app/api/admin/payment-methods/route.ts +10 -0
- package/templates/store-template/app/api/admin/products/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/products/bulk/route.ts +9 -0
- package/templates/store-template/app/api/admin/products/route.ts +9 -0
- package/templates/store-template/app/api/admin/products/stats/route.ts +10 -0
- package/templates/store-template/app/api/admin/reset-password/route.ts +10 -0
- package/templates/store-template/app/api/admin/settings/route.ts +11 -0
- package/templates/store-template/app/api/admin/setup/route.ts +10 -0
- package/templates/store-template/app/api/admin/setup-guide/manual-mark/route.ts +13 -0
- package/templates/store-template/app/api/admin/setup-guide/route.ts +10 -0
- package/templates/store-template/app/api/admin/shipping/carriers/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/carriers/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/rates/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/rates/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/shippo/api-key/route.ts +1 -0
- package/templates/store-template/app/api/admin/shipping/shippo/validate/route.ts +1 -0
- package/templates/store-template/app/api/admin/shipping/zones/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/zones/route.ts +9 -0
- package/templates/store-template/app/api/admin/stats/route.ts +9 -0
- package/templates/store-template/app/api/admin/stripe-status/route.ts +1 -0
- package/templates/store-template/app/api/admin/tax-zones/[id]/route.ts +7 -0
- package/templates/store-template/app/api/admin/tax-zones/route.ts +7 -0
- package/templates/store-template/app/api/admin/users/[id]/route.ts +14 -0
- package/templates/store-template/app/api/admin/users/route.ts +12 -0
- package/templates/store-template/app/api/admin-auth/[...nextauth]/route.ts +17 -0
- package/templates/store-template/app/api/analytics/track/route.ts +12 -0
- package/templates/store-template/app/api/auth/[...nextauth]/route.ts +19 -0
- package/templates/store-template/app/api/auth/forgot-password/route.ts +9 -0
- package/templates/store-template/app/api/auth/register/route.ts +9 -0
- package/templates/store-template/app/api/auth/resend-verification/route.ts +9 -0
- package/templates/store-template/app/api/auth/reset-password/route.ts +10 -0
- package/templates/store-template/app/api/auth/verify-email/route.ts +10 -0
- package/templates/store-template/app/api/categories/route.ts +10 -0
- package/templates/store-template/app/api/checkout/countries/route.ts +7 -0
- package/templates/store-template/app/api/checkout/discount/route.ts +9 -0
- package/templates/store-template/app/api/checkout/manual/route.ts +10 -0
- package/templates/store-template/app/api/checkout/payment-methods/route.ts +8 -0
- package/templates/store-template/app/api/checkout/pickup-locations/route.ts +8 -0
- package/templates/store-template/app/api/checkout/route.ts +10 -0
- package/templates/store-template/app/api/checkout/shipping/route.ts +21 -0
- package/templates/store-template/app/api/checkout/status/route.ts +10 -0
- package/templates/store-template/app/api/contact/route.ts +164 -0
- package/templates/store-template/app/api/media/presign/route.ts +7 -0
- package/templates/store-template/app/api/media/route.ts +7 -0
- package/templates/store-template/app/api/products/[slug]/route.ts +10 -0
- package/templates/store-template/app/api/products/route.ts +10 -0
- package/templates/store-template/app/api/store/settings/route.ts +12 -0
- package/templates/store-template/app/api/webhooks/stripe/route.ts +63 -0
- package/templates/store-template/app/auth/forgot-password/page.tsx +38 -0
- package/templates/store-template/app/auth/layout.tsx +17 -0
- package/templates/store-template/app/auth/reset-password/page.tsx +81 -0
- package/templates/store-template/app/auth/signin/page.tsx +62 -0
- package/templates/store-template/app/auth/signup/page.tsx +38 -0
- package/templates/store-template/app/auth/verify-email/page.tsx +185 -0
- package/templates/store-template/app/cart/page.tsx +137 -0
- package/templates/store-template/app/checkout/page.tsx +88 -0
- package/templates/store-template/app/checkout/success/page.tsx +50 -0
- package/templates/store-template/app/contact/layout.tsx +24 -0
- package/templates/store-template/app/contact/page.tsx +321 -0
- package/templates/store-template/app/faq/page.tsx +153 -0
- package/templates/store-template/app/globals.css +99 -0
- package/templates/store-template/app/layout.tsx +269 -0
- package/templates/store-template/app/not-found.tsx +35 -0
- package/templates/store-template/app/page.tsx +23 -0
- package/templates/store-template/app/privacy/page.tsx +281 -0
- package/templates/store-template/app/products/[slug]/ProductDetailClient.tsx +179 -0
- package/templates/store-template/app/products/[slug]/page.tsx +149 -0
- package/templates/store-template/app/products/layout.tsx +26 -0
- package/templates/store-template/app/products/page.tsx +102 -0
- package/templates/store-template/app/robots.ts +25 -0
- package/templates/store-template/app/sitemap.ts +76 -0
- package/templates/store-template/app/terms/page.tsx +313 -0
- package/templates/store-template/components/PathSyncBridge.tsx +61 -0
- package/templates/store-template/components/Providers.tsx +37 -0
- package/templates/store-template/components/layout/Footer.tsx +150 -0
- package/templates/store-template/components/layout/Header.tsx +162 -0
- package/templates/store-template/components/sections/.gitkeep +7 -0
- package/templates/store-template/components/sections/CTA.tsx +51 -0
- package/templates/store-template/components/sections/Features.tsx +91 -0
- package/templates/store-template/components/sections/Hero.tsx +85 -0
- package/templates/store-template/eslint.config.mjs +18 -0
- package/templates/store-template/lib/store-config.ts +77 -0
- package/templates/store-template/lib/store-policy.ts +68 -0
- package/templates/store-template/lib/utils.ts +21 -0
- package/templates/store-template/next-env.d.ts +6 -0
- package/templates/store-template/next.config.js +105 -0
- package/templates/store-template/package.json +32 -0
- package/templates/store-template/postcss.config.js +6 -0
- package/templates/store-template/proxy.ts +150 -0
- package/templates/store-template/public/rovela-logo.png +0 -0
- package/templates/store-template/tailwind.config.ts +74 -0
- package/templates/store-template/tsconfig.json +41 -0
- package/templates/store-template/types/next-auth.d.ts +32 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: customize-theme
|
|
3
|
+
description: Use when the user asks to change colors, fonts, spacing, layout, shadows, borders, or any visual styling. Covers CSS variables, globals.css, tailwind.config.ts, and theme tokens.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Theme Customization
|
|
7
|
+
|
|
8
|
+
> **Scope: STOREFRONT only.** Everything in this skill (these tokens, `globals.css` variables, Tailwind classes like `text-muted-foreground`/`bg-card`) styles the customer-facing store. The `/admin` dashboard has its OWN design system — `hsl(var(--admin-*))` tokens + `admin-*` classes, governed by CLAUDE.md §7.6 — and storefront tokens must never be used there.
|
|
9
|
+
|
|
10
|
+
## Key Files
|
|
11
|
+
|
|
12
|
+
- `/app/app/globals.css` — CSS variables (`:root` and `.dark` blocks)
|
|
13
|
+
- `/app/tailwind.config.ts` — Maps CSS variables to Tailwind classes
|
|
14
|
+
- `/app/.rovela/blueprint.json` — Original theme specification
|
|
15
|
+
|
|
16
|
+
## CSS Variable System
|
|
17
|
+
|
|
18
|
+
The theme uses HSL CSS variables. All colors are defined as `H S% L%` values (no `hsl()` wrapper — Tailwind adds it).
|
|
19
|
+
|
|
20
|
+
### Color Variables in globals.css
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
:root {
|
|
24
|
+
--background: 0 0% 100%;
|
|
25
|
+
--foreground: 0 0% 3.9%;
|
|
26
|
+
--primary: 0 0% 9%;
|
|
27
|
+
--primary-foreground: 0 0% 98%;
|
|
28
|
+
--secondary: 0 0% 96.1%;
|
|
29
|
+
--secondary-foreground: 0 0% 9%;
|
|
30
|
+
--muted: 0 0% 96.1%;
|
|
31
|
+
--muted-foreground: 0 0% 45.1%;
|
|
32
|
+
--accent: 0 0% 96.1%;
|
|
33
|
+
--accent-foreground: 0 0% 9%;
|
|
34
|
+
--destructive: 0 84.2% 60.2%;
|
|
35
|
+
--destructive-foreground: 0 0% 98%;
|
|
36
|
+
--border: 0 0% 89.8%;
|
|
37
|
+
--input: 0 0% 89.8%;
|
|
38
|
+
--ring: 0 0% 3.9%;
|
|
39
|
+
--card: 0 0% 100%;
|
|
40
|
+
--card-foreground: 0 0% 3.9%;
|
|
41
|
+
--popover: 0 0% 100%;
|
|
42
|
+
--popover-foreground: 0 0% 3.9%;
|
|
43
|
+
--radius: 0.5rem;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Usage in Components
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
// Correct — use semantic tokens
|
|
51
|
+
<div className="bg-background text-foreground">
|
|
52
|
+
<button className="bg-primary text-primary-foreground">
|
|
53
|
+
<p className="text-muted-foreground">
|
|
54
|
+
<div className="border border-border rounded-lg">
|
|
55
|
+
|
|
56
|
+
// Wrong — hardcoded colors bypass theming
|
|
57
|
+
<div className="bg-white text-black">
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## How to Change Colors
|
|
61
|
+
|
|
62
|
+
1. Read `/app/app/globals.css` to see current values
|
|
63
|
+
2. Modify the HSL values in `:root` (and `.dark` if dark mode exists)
|
|
64
|
+
3. Run error check after saving
|
|
65
|
+
|
|
66
|
+
### Example: Change primary to blue
|
|
67
|
+
|
|
68
|
+
```css
|
|
69
|
+
/* Before */
|
|
70
|
+
--primary: 0 0% 9%;
|
|
71
|
+
/* After */
|
|
72
|
+
--primary: 221 83% 53%;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## How to Change Fonts
|
|
76
|
+
|
|
77
|
+
1. Fonts are loaded in `/app/app/layout.tsx` via `next/font/google`
|
|
78
|
+
2. CSS variables `--font-heading` and `--font-body` are set in globals.css
|
|
79
|
+
3. Update both the import AND the CSS variable
|
|
80
|
+
|
|
81
|
+
### Example: Change heading font
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// In layout.tsx
|
|
85
|
+
import { Playfair_Display } from 'next/font/google';
|
|
86
|
+
const heading = Playfair_Display({ subsets: ['latin'], variable: '--font-heading' });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## How to Change Spacing/Radius
|
|
90
|
+
|
|
91
|
+
Modify `--radius` in globals.css:
|
|
92
|
+
- `0.25rem` — sharp/minimal
|
|
93
|
+
- `0.5rem` — balanced (default)
|
|
94
|
+
- `0.75rem` — rounded
|
|
95
|
+
- `1rem` — very rounded
|
|
96
|
+
|
|
97
|
+
## Responsive Design Rules
|
|
98
|
+
|
|
99
|
+
- Mobile-first: base styles for 320px, then `sm:`, `md:`, `lg:` breakpoints
|
|
100
|
+
- Touch targets: minimum 44x44px for buttons and links
|
|
101
|
+
- Body text: minimum 16px (prevents iOS zoom)
|
|
102
|
+
- Use `flex-wrap` and responsive grids, never horizontal scroll
|
|
103
|
+
|
|
104
|
+
## Brand-Expression Tokens — the polished feel layer
|
|
105
|
+
|
|
106
|
+
Beyond the shadcn color variables, every store should ship a fixed scaffold of brand-expression CSS variables in `globals.css` `:root`. These are the named primitives that separate a generic shadcn theme from a brand-expressive one. Same names every store, values per-brand.
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
:root {
|
|
110
|
+
/* shadcn color base (--primary, --background, etc.) above */
|
|
111
|
+
|
|
112
|
+
--primary-glow: [lighter HSL of primary, typically primary-300 from the derived scale];
|
|
113
|
+
--gradient-primary: linear-gradient(135deg, hsl(var(--primary)), hsl(var(--primary-glow)));
|
|
114
|
+
--gradient-subtle: linear-gradient(180deg, hsl(var(--background)), hsl(var(--muted)));
|
|
115
|
+
--shadow-elegant: 0 10px 30px -10px hsl(var(--primary) / 0.3);
|
|
116
|
+
--shadow-glow: 0 0 40px hsl(var(--primary-glow) / 0.4);
|
|
117
|
+
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### When the merchant asks for a polished feel
|
|
122
|
+
|
|
123
|
+
If the merchant asks to "make the hero feel more premium" / "add a glow to the CTAs" / "make this feel more designed" — reach for these tokens FIRST before inventing new ones.
|
|
124
|
+
|
|
125
|
+
Usage examples:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
// Hero CTA — brand-tinted shadow, smooth transition
|
|
129
|
+
<Button
|
|
130
|
+
style={{ background: 'var(--gradient-primary)', boxShadow: 'var(--shadow-elegant)', transition: 'var(--transition-smooth)' }}
|
|
131
|
+
className="hover:[box-shadow:var(--shadow-glow)]"
|
|
132
|
+
>
|
|
133
|
+
Shop now
|
|
134
|
+
</Button>
|
|
135
|
+
|
|
136
|
+
// Section with layered subtle gradient background
|
|
137
|
+
<section style={{ background: 'var(--gradient-subtle)' }}>
|
|
138
|
+
...
|
|
139
|
+
</section>
|
|
140
|
+
|
|
141
|
+
// Card with brand-glow halo
|
|
142
|
+
<Card className="shadow-[var(--shadow-glow)] transition-[var(--transition-smooth)]">
|
|
143
|
+
...
|
|
144
|
+
</Card>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Iteration rule
|
|
148
|
+
|
|
149
|
+
If a section feels generic mid-build, revisit `globals.css` + `tailwind.config.ts` to deepen these tokens (e.g. add `--gradient-radial-hero` for a specific section). NEVER change the merchant-frozen primary / secondary / heading / body — those are pinned by the platform per the Design Source of Truth routing in `/app/CLAUDE.md` §4. "Deepening" means adding expression tokens, not swapping brand identity.
|
|
150
|
+
|
|
151
|
+
## Editorial Accent — off-palette color, one specific section
|
|
152
|
+
|
|
153
|
+
If `theme_essentials.editorialAccent` is set in the brief, that hex is used at ONE specific location named in `editorialAccent.usage`. It is NOT bled across the page — it's an editorial moment, not a brand color. Examples:
|
|
154
|
+
- Warm coffee brand (brown + cream primaries) + sage editorial accent on the pull-quote ribbon
|
|
155
|
+
- Minimalist tech (black + white primaries) + warm amber editorial accent on the newsletter strip
|
|
156
|
+
|
|
157
|
+
When the merchant asks to "add a pop color" or "make the pull-quote section feel different," check if `editorialAccent` is set first — use it. If not set, propose a new one consistent with the chromatic story and update `globals.css` with a comment noting the single-use intent.
|
|
158
|
+
|
|
159
|
+
## Photography Style Lock — keep imagery cohesive
|
|
160
|
+
|
|
161
|
+
If `theme_essentials.photographyStyleLock` is set (5 axes: camera, lighting, composition, tone, subject), ALL image generation prompts MUST reuse those 5 axes verbatim. Only the subject-specific details vary per image; the rest stays constant.
|
|
162
|
+
|
|
163
|
+
When merchant asks "regenerate the hero photo" — keep the same STYLE LOCK, change only the subject specifics.
|
|
164
|
+
|
|
165
|
+
When merchant asks "make the photos feel more Aesop" — apply the `aesop-coded` PHOTOGRAPHY_STYLE_TEMPLATE (Hasselblad-coded medium format 80mm prime, north-window natural light 4500K, three-quarter view with generous negative space, warm cream/sepia tone, raw materials no people) and store the 5 axes in the brief's style lock for future iterations.
|
|
166
|
+
|
|
167
|
+
Other named templates: `glossier-coded`, `brutalist-raw`, `editorial-fashion`, `minimalist-product`, `studio-soft`, `documentary-natural`, `bright-saturated-pop`.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug-errors
|
|
3
|
+
description: Use when something is broken, not working, showing errors, or the user reports a bug. Covers the get_errors, read, fix, verify debugging loop.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Debug & Fix Errors
|
|
7
|
+
|
|
8
|
+
## Primary Tool
|
|
9
|
+
|
|
10
|
+
Use `get_errors` via next-devtools MCP for instant error checking (under 1 second).
|
|
11
|
+
|
|
12
|
+
**Never** run `npm run build` for error checking — it takes 30-60 seconds. Use `get_errors` instead.
|
|
13
|
+
|
|
14
|
+
## Debugging Workflow
|
|
15
|
+
|
|
16
|
+
1. **Check errors**: Run `get_errors` to see current TypeScript/compilation errors
|
|
17
|
+
2. **Read the file**: Read the relevant file(s) to understand the current implementation
|
|
18
|
+
3. **Identify root cause**: Look for the actual source of the issue, not just symptoms
|
|
19
|
+
4. **Make minimal fix**: Targeted changes only — avoid modifying unrelated code
|
|
20
|
+
5. **Verify fix**: Run `get_errors` again to confirm zero errors
|
|
21
|
+
6. **Check regressions**: Ensure related functionality still works
|
|
22
|
+
|
|
23
|
+
## Common Error Patterns
|
|
24
|
+
|
|
25
|
+
### Missing 'use client' Directive
|
|
26
|
+
**Symptom**: "useState is not defined" or "onClick handler in server component"
|
|
27
|
+
**Fix**: Add `'use client'` at the top of components using hooks or event handlers
|
|
28
|
+
|
|
29
|
+
### Import Resolution Errors
|
|
30
|
+
**Symptom**: "Module not found" or "Cannot find module"
|
|
31
|
+
**Fix**: Check SDK import paths against CLAUDE.md. Common mistake: wrong subpath.
|
|
32
|
+
```tsx
|
|
33
|
+
// Wrong
|
|
34
|
+
import { ProductCard } from '@rovela-ai/sdk'
|
|
35
|
+
// Correct
|
|
36
|
+
import { ProductCard } from '@rovela-ai/sdk/products'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Type Errors
|
|
40
|
+
**Symptom**: "Type X is not assignable to type Y"
|
|
41
|
+
**Fix**: Define proper interfaces for props. Check component prop types.
|
|
42
|
+
```tsx
|
|
43
|
+
interface Props {
|
|
44
|
+
title: string;
|
|
45
|
+
onClick: () => void;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Tailwind Class Errors
|
|
50
|
+
**Symptom**: Styles not applying or build warnings
|
|
51
|
+
**Fix**: Common mistake — `border-border` is invalid. Use `border` for border color with `border-border` for the utility.
|
|
52
|
+
|
|
53
|
+
### SDK Hook Errors
|
|
54
|
+
**Symptom**: Hook errors mentioning SDK files
|
|
55
|
+
**Fix**: The issue is likely in YOUR code, not the SDK. SDK internals are pre-validated. Focus debugging on files in `/app`.
|
|
56
|
+
|
|
57
|
+
## Stale Cache Issues
|
|
58
|
+
|
|
59
|
+
If errors persist after fixing, clear the build cache:
|
|
60
|
+
```
|
|
61
|
+
nextjs_call with port="3000", toolName="clear_cache"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then run `get_errors` again.
|
|
65
|
+
|
|
66
|
+
## When to Use npm run build
|
|
67
|
+
|
|
68
|
+
Only as **final verification** after all `get_errors` checks pass. Never use it as the primary debugging tool.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> **Languages**: on multilingual stores (`store_settings.enabled_locales` has
|
|
7
|
+
> more than one entry), every user-visible string must be authored in ALL
|
|
8
|
+
> enabled languages via the store dictionary (CLAUDE.md §5.5). Internal links
|
|
9
|
+
> always use `LocaleLink` from `@rovela-ai/sdk/core`.
|
|
10
|
+
|
|
11
|
+
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
12
|
+
|
|
13
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
14
|
+
|
|
15
|
+
## Design Thinking
|
|
16
|
+
|
|
17
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
18
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
19
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
|
20
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
21
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
22
|
+
|
|
23
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
|
24
|
+
|
|
25
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
26
|
+
- Production-grade and functional
|
|
27
|
+
- Visually striking and memorable
|
|
28
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
29
|
+
- Meticulously refined in every detail
|
|
30
|
+
|
|
31
|
+
## Frontend Aesthetics Guidelines
|
|
32
|
+
|
|
33
|
+
Focus on:
|
|
34
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
35
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
36
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
|
37
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
38
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
|
39
|
+
|
|
40
|
+
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
|
41
|
+
|
|
42
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
|
43
|
+
|
|
44
|
+
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
|
45
|
+
|
|
46
|
+
Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
|
47
|
+
|
|
48
|
+
## Content Voice — short, specific, sounds-human
|
|
49
|
+
|
|
50
|
+
The merchant will replace most copy with their own product details. Your job is short, specific placeholder content that demonstrates voice and structure — not paragraphs the merchant has to delete before they can think. This applies to BOTH initial generation AND chat-edit rewrites.
|
|
51
|
+
|
|
52
|
+
**Length caps (hard, per section):**
|
|
53
|
+
- Hero: headline ≤ 8 words. Subhead ≤ 14 words. NO additional paragraph below the subhead.
|
|
54
|
+
- Features: 3–4 cards. Each card: title ≤ 4 words + description ≤ 16 words. Total feature prose ≤ 80 words.
|
|
55
|
+
- Trust / About: 2–3 sentences, ≤ 80 words total. No three-paragraph "Our story" essay. No "Founded in..." preamble unless the merchant actually said so.
|
|
56
|
+
- CTA: headline ≤ 8 words. Subhead ≤ 12 words. Button label ≤ 3 words.
|
|
57
|
+
- FAQ (when included): question ≤ 12 words, answer ≤ 30 words, max 5 entries.
|
|
58
|
+
|
|
59
|
+
**Banned vocabulary (AI tells — do NOT use in storefront copy):**
|
|
60
|
+
elevate, enhance, delve, embrace, embark, leverage, unlock, navigate, harness, streamline, optimize, seamless, robust, transform, empower, discover, unveil, journey, treasure trove, game-changer, world-class, cutting-edge, next-generation, premium, modern, clean, sophisticated, elevated.
|
|
61
|
+
|
|
62
|
+
**Banned structures:**
|
|
63
|
+
- "Not just X — it's Y" / "It's not about X, it's about Y" (AI negation cliché).
|
|
64
|
+
- "In today's world..." / "In the digital age..." (throat-clearing preambles).
|
|
65
|
+
- Em-dash overuse: max 1 em-dash per section.
|
|
66
|
+
- Generic adjective stacks ("premium, modern, clean") — guaranteed AI tell.
|
|
67
|
+
|
|
68
|
+
**Write like a human who knows the product:**
|
|
69
|
+
- Specifics over abstractions: "hand-stitched Italian calfskin" beats "premium leather."
|
|
70
|
+
- Real numbers, names, places: "ships in 4 days from Brooklyn" beats "fast shipping."
|
|
71
|
+
- Verbs over adjectives: "roasted in small batches" beats "high-quality coffee."
|
|
72
|
+
- Sensory details for taste/feel/touch: "tastes of charred sugar and tobacco" beats "rich flavor."
|
|
73
|
+
- Plain English: "for people who" beats "designed for the discerning individual who."
|
|
74
|
+
|
|
75
|
+
Source the specifics from the merchant's business_description in CLAUDE.md §2 first. If the merchant wrote one good concrete sentence, lift that language verbatim or close. The brief's `brand_essentials.voice.vocabulary.preferred` list is the safe phrase pool; `vocabulary.avoid` is the additional per-merchant banned list on top of the universal one above.
|
|
76
|
+
|
|
77
|
+
**Chat-edit application**: when the merchant asks you to rewrite a section ("make the hero punchier", "shorten this", "less AI-sounding"), the same caps apply. Going OVER cap is a regression — never lengthen unless the merchant explicitly asked for more copy.
|
|
78
|
+
|
|
79
|
+
## Aesthetic Ritual — commit before you code
|
|
80
|
+
|
|
81
|
+
Before writing any major redesign or new section, pause and write a 4-bullet commitment in your narration. This forces concrete decisions and prevents drift to safe defaults. This applies to BOTH initial generation AND chat-edit redesigns ("make the hero more premium", "redesign this section to feel editorial").
|
|
82
|
+
|
|
83
|
+
1. **What this brand evokes** — one sentence. Concrete, sensory, specific. NOT "premium / modern / clean."
|
|
84
|
+
2. **Design inspirations** — one sentence. If the merchant referenced specific designs or supplied screenshots, those ARE your inspirations; name them. Otherwise name 1–2 specific influences (an aesthetic era, a specific brand category, a material world).
|
|
85
|
+
3. **Palette commitment** — list the primary + secondary + accent hex codes you're committing to. If editing, confirm the existing palette OR propose specific replacements with reasoning.
|
|
86
|
+
4. **Motion commitment** — list the 2–3 specific motion moments you'll implement (entrance, hover, signature). Cite ms timings.
|
|
87
|
+
|
|
88
|
+
## Component Customization Pattern — variants, not inline overrides
|
|
89
|
+
|
|
90
|
+
When customizing buttons / cards / pills / badges from shadcn or the SDK, CREATE NEW cva variants using semantic tokens. Variant definitions live in the component file's cva() block.
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// ✅ CORRECT — new variant lives in the component
|
|
94
|
+
const buttonVariants = cva("...", {
|
|
95
|
+
variants: {
|
|
96
|
+
variant: {
|
|
97
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
98
|
+
hero: "bg-gradient-primary text-primary-foreground shadow-elegant hover:shadow-glow transition-smooth",
|
|
99
|
+
editorial: "bg-transparent border border-foreground/20 text-foreground hover:bg-foreground hover:text-background",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// At the call site:
|
|
105
|
+
<Button variant="hero">Shop now</Button>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
// ❌ WRONG — inline overrides bypass the design system
|
|
110
|
+
<Button className="bg-primary/90 hover:bg-primary text-white px-6 shadow-xl">
|
|
111
|
+
Shop now
|
|
112
|
+
</Button>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Inline raw-class overrides at call sites rot. Variants compose, stay coherent across chat-edits, and let the design system evolve as a single unit.
|
|
116
|
+
|
|
117
|
+
## Contrast Trap — real bug-class warning
|
|
118
|
+
|
|
119
|
+
When alternating section backgrounds (background → muted → card → background), verify text contrast in BOTH light AND dark modes. White text on bg-muted in light-mode often disappears; dark text on bg-card in dark-mode often does too. Sanity-check every section-pair you ship — this is the single most common visual bug class.
|
|
120
|
+
|
|
121
|
+
## Layout Vocabulary — pattern catalog for chat-edits
|
|
122
|
+
|
|
123
|
+
When the merchant asks to change a section's layout (e.g. "make the hero more editorial" / "switch the products to a bento grid" / "this footer feels generic, can it be more like Aesop's"), look up the named pattern from one of these catalogs and apply the matching skeleton.
|
|
124
|
+
|
|
125
|
+
**HERO PATTERNS** (9):
|
|
126
|
+
- `split` — text + image side-by-side, equal weight
|
|
127
|
+
- `center` — text-only, vertically stacked, max-w-3xl
|
|
128
|
+
- `bg-image` — full-bleed photographic bg + text overlay
|
|
129
|
+
- `immersive` — viewport-height with full-bleed bg; cinematic
|
|
130
|
+
- `editorial` — asymmetric magazine, oversized type on non-center column, image floats
|
|
131
|
+
- `bento` — compartmentalized grid hero (4-6 tiles, one large + smaller + text card)
|
|
132
|
+
- `type-first` — kinetic huge typography dominates; size jump 5×+
|
|
133
|
+
- `parallax-bg` — full-bleed with CSS 3D parallax (translateZ + perspective)
|
|
134
|
+
- `video-bg` — variant of immersive with autoPlay/muted/loop/playsInline video
|
|
135
|
+
|
|
136
|
+
**SECTION SEPARATION** (6):
|
|
137
|
+
- `soft` — subtle bg-color shifts, no borders
|
|
138
|
+
- `clean` — distinct stripes with whitespace/thin borders
|
|
139
|
+
- `cards` — every section wrapped in card chrome
|
|
140
|
+
- `editorial-interleave` — non-commerce section every 2 commerce (pull-quote / craft vignette / founder photo)
|
|
141
|
+
- `scroll-snap` — full-page snap sections (scroll-snap-type: y mandatory)
|
|
142
|
+
- `asymmetric-alt` — alternate left → right → full-bleed → center
|
|
143
|
+
|
|
144
|
+
**PRODUCT SHOWCASE** (6):
|
|
145
|
+
- `grid` — uniform 3-col responsive grid
|
|
146
|
+
- `list` — vertical full-width rows
|
|
147
|
+
- `lookbook` — asymmetric, one hero + smaller tiles
|
|
148
|
+
- `editorial-2col` — magazine spread, product + prose alternating
|
|
149
|
+
- `horizontal-snap` — horizontal scroll-snap carousel
|
|
150
|
+
- `bento-grid` — hero product + smaller tiles + ONE text/copy card peer
|
|
151
|
+
|
|
152
|
+
**HEADER PATTERNS** (5):
|
|
153
|
+
- `transparent-to-solid` — transparent on load, solidifies on scroll
|
|
154
|
+
- `sticky-condensed` — shrinks + condenses after 80px scroll
|
|
155
|
+
- `mega-menu` — compact top + rich hover mega-menus (Stripe-style)
|
|
156
|
+
- `editorial-minimal` — centered logo, sparse nav, no utility row (Aesop)
|
|
157
|
+
- `utility-first` — cart + search prominent, nav secondary
|
|
158
|
+
|
|
159
|
+
**FOOTER PATTERNS** (4):
|
|
160
|
+
- `editorial-massive` — multi-column newsletter + values + craft-story + sitemap
|
|
161
|
+
- `minimal-utility` — logo + 5 links + copyright, one row
|
|
162
|
+
- `newsletter-first` — newsletter dominates, sitemap secondary
|
|
163
|
+
- `brand-narrative` — long-form brand-story prose body (Aesop)
|
|
164
|
+
|
|
165
|
+
**TYPOGRAPHY MODES** (5):
|
|
166
|
+
- `decorative` — standard hierarchy, conservative
|
|
167
|
+
- `kinetic` — aggressive jumps 5×+, weight extremes (300/900), animated stagger
|
|
168
|
+
- `editorial-display` — refined oversized display (200 or 700), generous tracking, slow fade
|
|
169
|
+
- `marquee` — scrolling type bands as brand statement
|
|
170
|
+
- `variable-axis` — variable fonts with weight/width transitions tied to scroll
|
|
171
|
+
|
|
172
|
+
**SIGNATURE MOVES** (12 named): slow-page-fade, cursor-halo, scroll-progress-bar, parallax-vertical-mark, letter-stagger-reveal, color-shift-on-scroll, sticky-cta-reveal, marquee-headline, ambient-grain, intersection-reveal, custom-cursor, page-load-stagger. Pick ONE per store; CSS-only when possible; respect `prefers-reduced-motion`.
|
|
173
|
+
|
|
174
|
+
**SIGNATURE COMPONENT CATEGORIES** (7): decorative-divider, custom-product-card, themed-indicator, narrative-interlude, signature-button, decorative-frame, parallax-mark.
|
|
175
|
+
|
|
176
|
+
When CLAUDE.md §4's Design Source of Truth routing table names a pattern, that pattern is FROZEN — do not propose alternatives unless the merchant explicitly asks to change it.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: generate-images
|
|
3
|
+
description: Use when generating visual assets (hero, product photos, feature graphics, section backgrounds, testimonial headshots) for a store. Covers the mcp__r2__generate_image tool, aspect ratios per section, prompt writing, filename conventions, and the gradient fallback. Triggers on any mention of image generation, hero image, product photos, or missing visuals.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Generate Images
|
|
7
|
+
|
|
8
|
+
## Rule zero
|
|
9
|
+
|
|
10
|
+
**Call `mcp__r2__generate_image` directly from this skill's execution context, in sequence.** Directly-spawned `Agent`/`Task` subagents outside of skill context do not reliably inherit MCP tool access (github anthropics/claude-code #7296, #38920) — delegation outside this skill means silent failure and missing images. Inside this skill, calls you make execute in a context that has MCP access, so just call the tool directly.
|
|
11
|
+
|
|
12
|
+
## When to generate
|
|
13
|
+
|
|
14
|
+
| Surface | Count (typical full homepage) |
|
|
15
|
+
|---|---|
|
|
16
|
+
| **Hero** — background or foreground image | 1 |
|
|
17
|
+
| **Features** — one image per feature card | 1–3 of the most visual cards |
|
|
18
|
+
| **Products** — photo per seed product if no image provided | 1 per product |
|
|
19
|
+
| **Testimonials** — headshots (optional, brand-dependent) | 0–1 |
|
|
20
|
+
| **Trust / other sections** | Only if the blueprint requests imagery |
|
|
21
|
+
|
|
22
|
+
Total: around 5–6 `mcp__r2__generate_image` calls for a typical full homepage generation. Sequential. ~30–45 seconds total.
|
|
23
|
+
|
|
24
|
+
## Prompt format
|
|
25
|
+
|
|
26
|
+
40–75 words. Anchor on the Visual Creative Brief in CLAUDE.md §4 (personality, color philosophy, imagery direction). Include photography terminology: lighting, angle, subject, mood, color palette, lens, texture.
|
|
27
|
+
|
|
28
|
+
Example (Cofme — editorial Parisian atelier):
|
|
29
|
+
|
|
30
|
+
> Editorial Parisian atelier, unmade silk pillows in dusty rose and cream, morning light streaming through tall windows, warm bronze accents, shallow depth of field, soft grainy texture, 85mm portrait lens, 4:3 aspect ratio.
|
|
31
|
+
|
|
32
|
+
Example (Tech / SaaS store):
|
|
33
|
+
|
|
34
|
+
> Minimal product flat-lay on matte charcoal surface, single cyan accent light from upper-left, subtle blue gradient background, precise geometric composition, studio lighting with soft shadows, 50mm macro lens, 1:1 square aspect ratio.
|
|
35
|
+
|
|
36
|
+
## Aspect ratios by context
|
|
37
|
+
|
|
38
|
+
| Context | Aspect | Notes |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| Hero — full-screen layout | 16:9 | Landscape, widescreen |
|
|
41
|
+
| Hero — split layout | 3:4 | Portrait side panel |
|
|
42
|
+
| Feature card | 4:3 | Balanced landscape |
|
|
43
|
+
| Product photo | 1:1 | Square grid |
|
|
44
|
+
| Testimonial portrait | 1:1 | Square headshot |
|
|
45
|
+
| Section background | 16:9 | Wide background |
|
|
46
|
+
|
|
47
|
+
Pass the aspect ratio both in the prompt text AND as the `aspect_ratio` parameter to `mcp__r2__generate_image`.
|
|
48
|
+
|
|
49
|
+
## Filename convention
|
|
50
|
+
|
|
51
|
+
`{section}-{index}-{slug}.webp` — for example `hero-1-atelier.webp`, `feature-2-bespoke-pillows.webp`, `product-3-silk-cream.webp`. Human-readable and visible in R2 storage when debugging.
|
|
52
|
+
|
|
53
|
+
## Fallback on error
|
|
54
|
+
|
|
55
|
+
If `mcp__r2__generate_image` returns an error (Gemini rate limit, safety block, timeout), use a CSS gradient with the brand primary colors from the Visual Creative Brief. **Never** hardcode external URLs (Unsplash, placeholder.com, picsum.photos). **Never** leave a broken `<img>` tag.
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
// Fallback pattern — no broken images, no external URLs
|
|
59
|
+
<div className="bg-gradient-to-br from-primary/20 via-primary/10 to-transparent h-full w-full" />
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Canonical call sequence for a full homepage
|
|
63
|
+
|
|
64
|
+
**Preferred — single batched call** (`mcp__r2__generate_images`, plural):
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
mcp__r2__generate_images({
|
|
68
|
+
images: [
|
|
69
|
+
{ prompt: "...", filename: "hero-1-{slug}", aspect_ratio: "16:9" },
|
|
70
|
+
{ prompt: "...", filename: "feature-1-{slug}", aspect_ratio: "4:3" },
|
|
71
|
+
{ prompt: "...", filename: "feature-2-{slug}", aspect_ratio: "4:3" },
|
|
72
|
+
{ prompt: "...", filename: "feature-3-{slug}", aspect_ratio: "4:3" },
|
|
73
|
+
{ prompt: "...", filename: "about-1-{slug}", aspect_ratio: "4:3" },
|
|
74
|
+
{ prompt: "...", filename: "product-1-{slug}", aspect_ratio: "1:1" },
|
|
75
|
+
{ prompt: "...", filename: "product-2-{slug}", aspect_ratio: "1:1" },
|
|
76
|
+
{ prompt: "...", filename: "product-3-{slug}", aspect_ratio: "1:1" },
|
|
77
|
+
]
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Returns `{ images: [{ success, url?, key?, size?, error? }, ...] }` preserving input order. The server fans out at concurrency 4 → typical 8-image batch lands in ~12s wall-clock vs ~48s sequential. **Use this for the initial homepage build whenever you have 3+ images planned up front.** Max 12 entries per call.
|
|
82
|
+
|
|
83
|
+
**Per-entry fallback contract is unchanged** — if `images[i].success === false`, use a CSS gradient for that one image only and continue with the rest. Don't abort the page over one Gemini error.
|
|
84
|
+
|
|
85
|
+
**Singular `mcp__r2__generate_image` is still preferred for:**
|
|
86
|
+
|
|
87
|
+
- Edit-mode iteration (merchant asks "regenerate just the hero" — one image at a time)
|
|
88
|
+
- Workflows where the prompt for image N depends on what image N-1 produced
|
|
89
|
+
- <3 images total
|
|
90
|
+
|
|
91
|
+
**Sequential singular fallback** (if `generate_images` ever returns an error for the whole call):
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
1. mcp__r2__generate_image — hero (16:9 or 3:4 depending on layout)
|
|
95
|
+
2. mcp__r2__generate_image — feature 1 (4:3)
|
|
96
|
+
3. mcp__r2__generate_image — feature 2 (4:3)
|
|
97
|
+
...
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Call them one after the other in THIS session. Not via Agent/Task. ~6s each, ~30-45s total for a homepage — slower than the plural batch but guaranteed-compatible with older sandbox images.
|
|
101
|
+
|
|
102
|
+
## Common anti-patterns
|
|
103
|
+
|
|
104
|
+
- ❌ `Agent(prompt="Generate 5 images via mcp__r2__generate_image")` outside this skill → subagent won't have MCP access, silent failure
|
|
105
|
+
- ❌ "I'll use Task in parallel to generate all images outside the skill" → don't; stay inside this skill's execution
|
|
106
|
+
- ❌ Using singular `generate_image` 8 times in a row for a homepage build → use the plural tool instead, saves ~30s of wall-clock
|
|
107
|
+
- ❌ Using plural `generate_images` for a single-image edit-mode iteration → wasteful, use singular
|
|
108
|
+
- ❌ Treating `generate_images` whole-call failure differently from per-image failure → check `images[i].success` per entry, not the call's outer success
|
|
109
|
+
- ❌ Using `imageUrl` from blueprint without checking if it's null/empty
|
|
110
|
+
- ❌ `src="https://images.unsplash.com/..."` or any other external URL
|
|
111
|
+
- ❌ Leaving `<img>` without src — always either a generated URL or replace with a gradient `<div>`
|
|
112
|
+
- ✅ One plural `mcp__r2__generate_images` call for the initial homepage build
|
|
113
|
+
- ✅ One-by-one singular `mcp__r2__generate_image` calls for edit-mode iteration
|
|
114
|
+
- ✅ Brand-specific scene descriptions drawn from the Visual Creative Brief
|
|
115
|
+
- ✅ Gradient `<div>` fallback if a single image's `success` is `false`
|