@getcoherent/cli 0.6.6 → 0.6.8

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/index.js CHANGED
@@ -1,11 +1,19 @@
1
1
  import {
2
+ CORE_CONSTRAINTS,
3
+ DESIGN_QUALITY,
4
+ DESIGN_THINKING,
5
+ INTERACTION_PATTERNS,
6
+ VISUAL_DEPTH,
2
7
  generateArchitecturePlan,
8
+ getDesignQualityForType,
3
9
  getPageGroup,
4
10
  getPageType,
11
+ inferPageTypeFromRoute,
5
12
  loadPlan,
6
13
  routeToKey,
7
- savePlan
8
- } from "./chunk-F3NMRT3Z.js";
14
+ savePlan,
15
+ selectContextualRules
16
+ } from "./chunk-EXF37DQB.js";
9
17
  import {
10
18
  __require
11
19
  } from "./chunk-3RG5ZIWI.js";
@@ -4162,891 +4170,6 @@ Make it responsive and visually appealing.
4162
4170
  `;
4163
4171
  }
4164
4172
 
4165
- // src/agents/design-constraints.ts
4166
- var DESIGN_THINKING = `
4167
- ## DESIGN THINKING (answer internally BEFORE writing code)
4168
-
4169
- 1. PURPOSE \u2014 What is this page's job? (inform / convert / navigate / manage / onboard)
4170
- 2. AUDIENCE \u2014 Who uses it? (developer / executive / consumer / admin)
4171
- 3. MOOD \u2014 What should the user FEEL? (confident, excited, calm, focused, impressed)
4172
- 4. FOCAL POINT \u2014 What ONE element draws the eye first on this page?
4173
- 5. RHYTHM \u2014 Where should the page breathe (spacious) vs feel dense (packed with data)?
4174
-
4175
- Then commit to:
4176
- - One DOMINANT visual element per page (hero image, large metric, gradient header, feature grid)
4177
- - One ACCENT technique per page (gradient text, colored icon containers, glass card, background pattern)
4178
- - One moment of CONTRAST (large vs small, dense vs spacious, dark vs light section)
4179
-
4180
- DO NOT make every section look the same. Vary density, background treatment, and visual weight.
4181
- Every page should have a clear visual hierarchy \u2014 if you squint, the structure should still be obvious.
4182
- `;
4183
- var CORE_CONSTRAINTS = `
4184
- SHADCN/UI DESIGN CONSTRAINTS (MANDATORY \u2014 these rules produce professional UI):
4185
-
4186
- TYPOGRAPHY (most impactful rules):
4187
- - Base text: text-sm (14px). NEVER use text-base (16px) as body text.
4188
- - Card/section titles: text-sm font-medium. NEVER text-lg or text-xl on card titles.
4189
- - Page title: text-2xl font-bold tracking-tight (only place for large text).
4190
- - Metric/KPI values: text-2xl font-bold (the ONLY other place for large text).
4191
- - Muted/secondary: text-sm text-muted-foreground (or text-xs text-muted-foreground).
4192
- - Create hierarchy through font WEIGHT (medium \u2192 semibold \u2192 bold), NOT font SIZE.
4193
-
4194
- COLORS \u2014 ONLY SEMANTIC TOKENS (zero raw colors):
4195
- - Backgrounds: bg-background, bg-muted, bg-muted/50, bg-card, bg-primary, bg-secondary, bg-destructive.
4196
- - Text: text-foreground (default), text-muted-foreground, text-primary-foreground.
4197
- - Borders: border (no color suffix \u2014 uses CSS variable). border-b for headers.
4198
- - BANNED: bg-gray-*, bg-blue-*, bg-slate-*, text-gray-*, ANY raw Tailwind color. The validator REJECTS these.
4199
-
4200
- SPACING (restricted palette \u2014 only multiples of 4px):
4201
- - Page content padding: p-4 lg:p-6. Gap between major sections: gap-6 md:gap-8.
4202
- - Gap inside a section: gap-4 md:gap-6. Card internal gap: gap-2. Max padding: p-6.
4203
- - Prefer gap-* over space-x-* / space-y-* at page/section level.
4204
-
4205
- LAYOUT PATTERNS:
4206
- - Stats/KPI grid: grid gap-4 md:grid-cols-2 lg:grid-cols-4
4207
- - Card grid (3 col): grid gap-4 md:grid-cols-3
4208
- - Full-height page: min-h-svh (not min-h-screen)
4209
- - Centered form (login/signup): flex min-h-svh flex-col items-center justify-center p-6 md:p-10 \u2192 div w-full max-w-md
4210
- - Page content wrapper: flex flex-1 flex-col gap-4 p-4 lg:p-6
4211
- - Responsive: primary md: and lg:. Use sm:/xl: only when genuinely needed. Avoid 2xl:. NEVER arbitrary like min-[800px].
4212
-
4213
- COMPONENT IMPORTS (mandatory \u2014 NEVER native HTML):
4214
- - NEVER use native <button>. Always: import { Button } from "@/components/ui/button".
4215
- - NEVER use native <input type="checkbox"> for toggles. Always: import { Checkbox } or { Switch }.
4216
- - NEVER use native <select>. Always: import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem }.
4217
- - NEVER use native <input> alone. Always pair with Label.
4218
- - NEVER use native <table>. Always: import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell }.
4219
- SHADCN COMPONENTS ONLY (CRITICAL):
4220
- - ALWAYS import and use shadcn components: Button, Input, Label, Textarea, Badge, Checkbox, Switch, Select, Table, etc.
4221
- - Form field pattern: <div className="space-y-2"><Label htmlFor="x">Name</Label><Input id="x" /></div>
4222
- - Card with form: Card > CardHeader(title+description) > CardContent(form fields) > CardFooter(Button)
4223
- - Button variants: default, secondary, outline, ghost, destructive.
4224
-
4225
- LINKS & INTERACTIVE STATES (consistency is critical):
4226
- - Text links (inline): text-sm text-muted-foreground underline underline-offset-4 hover:text-foreground transition-colors
4227
- - ALL links on the SAME page MUST use the SAME style. Never mix underlined and non-underlined text links.
4228
- - ALL Button variants MUST have: hover: state, focus-visible:ring-2 focus-visible:ring-ring, active: state, disabled:opacity-50.
4229
- - ALL interactive elements MUST have visible hover and focus-visible states.
4230
- - CRITICAL: Every <Link> MUST have an href prop. Missing href causes runtime errors. Never use <Link className="..."> or <Button asChild><Link> without href.
4231
- - When shared components exist (@/components/shared/*), ALWAYS import and use them instead of re-implementing similar patterns inline.
4232
-
4233
- ICONS:
4234
- - Size: ALWAYS size-4 (16px). Color: ALWAYS text-muted-foreground. Import: ALWAYS from lucide-react.
4235
- - ALWAYS add shrink-0 to icon className to prevent flex containers from squishing them.
4236
-
4237
- ANTI-PATTERNS (NEVER DO):
4238
- - text-base as body text \u2192 use text-sm
4239
- - text-lg/xl on card titles \u2192 use text-sm font-medium
4240
- - Raw colors (bg-gray-100, text-blue-600) \u2192 use semantic tokens
4241
- - shadow-md or heavier \u2192 use shadow-sm or none
4242
- - padding > p-6 \u2192 max is p-6
4243
- - Raw <button> or <input> \u2192 always use Button, Input from @/components/ui/
4244
- - Mixing link styles on the same page \u2192 pick ONE style
4245
- - Interactive elements without hover/focus states
4246
-
4247
- COMPONENT VARIANT RULES (CRITICAL):
4248
- - NEVER use <Button> with custom bg-*/text-* classes for navigation or tabs without variant="ghost".
4249
- The default Button variant sets bg-primary, so custom text-muted-foreground or bg-accent classes will conflict.
4250
- BAD: <Button className="text-muted-foreground hover:bg-accent">Tab</Button>
4251
- GOOD: <Button variant="ghost" className="text-muted-foreground">Tab</Button>
4252
- BEST: Use shadcn <Tabs> / <TabsList> / <TabsTrigger> for tab-style navigation.
4253
- - For sidebar navigation buttons, ALWAYS use variant="ghost" with active-state classes:
4254
- <Button variant="ghost" className={cn("w-full justify-start", isActive && "bg-accent font-medium")}>
4255
- - For filter toggle buttons, use variant={isActive ? 'default' : 'outline'} \u2014 NOT className toggling.
4256
-
4257
- CONTENT (zero placeholders):
4258
- - NEVER: "Lorem ipsum", "Card content", "Description here"
4259
- - ALWAYS: Real, contextual content. Realistic metric names, values, dates.
4260
- `;
4261
- var DESIGN_QUALITY_COMMON = `
4262
- ## DESIGN QUALITY \u2014 COMMON
4263
-
4264
- ### Typography Hierarchy
4265
- - Page headline (h1): text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight leading-[1.1]
4266
- - Section titles (h2): text-2xl md:text-3xl font-bold
4267
- - Card titles (h3): text-sm font-semibold (never text-base or text-lg)
4268
- - Body text: text-sm text-muted-foreground leading-relaxed
4269
- - The SIZE DIFFERENCE between levels must be dramatic, not subtle
4270
-
4271
- ### Visual Depth & Layers
4272
- - Cards: bg-card border border-border/15 rounded-xl (not rounded-md)
4273
- - Cards on dark pages: bg-zinc-900/50 border-border/10 backdrop-blur-sm
4274
- - Cards MUST have hover state: hover:border-border/30 transition-colors
4275
- - Sections alternate between bg-background and bg-muted/5 for rhythm
4276
- - Section dividers: border-t border-border/10 (subtle, not heavy)
4277
-
4278
- ### Buttons with Icons
4279
- - Buttons containing text + icon: ALWAYS use inline-flex items-center gap-2 whitespace-nowrap
4280
- - Icon inside button: h-4 w-4 (never larger), placed AFTER text for arrows, BEFORE text for action icons
4281
- - NEVER let button content wrap to multiple lines \u2014 use whitespace-nowrap on the Button component
4282
- - CTA buttons: use the Button component, NEVER raw <button> or <a> styled as button
4283
-
4284
- ### Accent Color Discipline
4285
- - ONE accent color per page (primary or emerald-400)
4286
- - Use for: CTAs, terminal text, check icons, feature icon backgrounds, active states
4287
- - NEVER mix blue + purple + emerald on same page
4288
- - Badge: outline style (border-border/30 bg-transparent) not filled color
4289
- - Status icons: text-emerald-400 for positive, text-red-400 for negative
4290
-
4291
- ### Dark Theme Implementation
4292
- - html element: className="dark"
4293
- - Background: use CSS variables from globals.css dark section
4294
- - Text: text-foreground for primary, text-muted-foreground for secondary
4295
- - NEVER hardcode dark colors (bg-gray-900) \u2014 always use semantic tokens
4296
- - Cards and elevated elements: slightly lighter than background (bg-card or bg-zinc-900/50)
4297
- `;
4298
- var DESIGN_QUALITY_MARKETING = `
4299
- ## DESIGN QUALITY \u2014 MARKETING PAGES
4300
-
4301
- ### Spacing Rhythm (3 distinct levels)
4302
- - Between sections: py-20 md:py-28 (generous)
4303
- - Within sections (title to content): mb-12 md:mb-16
4304
- - Within cards: p-6 (compact)
4305
- - Between cards in grid: gap-5 (tight)
4306
- - NEVER uniform spacing everywhere \u2014 contrast creates rhythm
4307
-
4308
- ### Hero headline
4309
- - Landing/marketing hero headline: text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight leading-[1.05]
4310
-
4311
- ### Icons in Feature Cards
4312
- - Wrap in colored container: bg-primary/10 rounded-lg p-2.5
4313
- - Icon color: text-primary (or text-emerald-400 for dark themes)
4314
- - Icon size: h-5 w-5 inside the container
4315
- - NEVER bare icons floating in a card without container
4316
-
4317
- ### Terminal / Code Blocks
4318
- - Background: bg-zinc-950 (near-black, not gray)
4319
- - Border: border-border/10 rounded-xl
4320
- - Text: font-mono text-sm text-emerald-400
4321
- - Prompt: text-emerald-500 "$ " prefix (green dollar sign)
4322
- - Title bar (optional): flex with 3 dots (bg-zinc-700 rounded-full w-2.5 h-2.5) + title text-zinc-500 text-[11px]
4323
- - Copy button: text-zinc-500 hover:text-zinc-300
4324
-
4325
- ### Hero Section
4326
- - Minimum height: min-h-[80vh] flex items-center justify-center
4327
- - Content: centered, max-w-3xl, flex flex-col items-center text-center gap-8
4328
- - Badge above headline: small, outline, text-xs tracking-wide
4329
- - Gradient text on key phrase: bg-gradient-to-r from-white to-zinc-500 bg-clip-text text-transparent
4330
- - Subheadline: text-muted-foreground max-w-2xl text-base md:text-lg
4331
- - CTA row: flex items-center gap-4
4332
-
4333
- ### Comparison Sections (before/after, with/without)
4334
- - Two cards side by side: grid md:grid-cols-2 gap-6
4335
- - Negative card: neutral border, items with X icon text-red-400
4336
- - Positive card: accent border (border-emerald-500/20), items with Check icon text-emerald-400
4337
- - Header of each card: text-sm font-semibold uppercase tracking-wider
4338
-
4339
- ### Step/Process Sections
4340
- - Numbered steps: circle with border, number inside (w-10 h-10 rounded-full border border-border/30 text-sm)
4341
- - Label above: text-xs font-semibold tracking-widest uppercase text-muted-foreground
4342
-
4343
- ### Footer
4344
- - Minimal: border-t border-border/10, py-10
4345
- - Content: text-sm text-muted-foreground
4346
- - Links: hover:text-foreground transition-colors
4347
- - Layout: flex justify-between on desktop, stack on mobile
4348
-
4349
- NEVER include app-style elements (sidebar widgets, data tables, filters) on marketing pages.
4350
- `;
4351
- var DESIGN_QUALITY_APP = `
4352
- ## DESIGN QUALITY \u2014 APP PAGES
4353
-
4354
- ### Spacing
4355
- - gap-4 md:gap-6 between sections
4356
- - p-4 lg:p-6 content padding
4357
- - Within cards: p-4 to p-6 (compact)
4358
- - Between cards in grid: gap-4 (tight)
4359
-
4360
- ### Layout
4361
- - Data tables, card grids, filters, stat rows
4362
- - Page wrapper: flex flex-1 flex-col gap-4 p-4 lg:p-6
4363
- - Stats grid: grid gap-4 md:grid-cols-2 lg:grid-cols-4
4364
- - Content: functional, scannable, data-dense
4365
-
4366
- ### Toolbars & Filters
4367
- - Filter row: flex flex-wrap items-center gap-2
4368
- - Search input: MUST use flex-1 to fill remaining horizontal space
4369
- - Filters/selects: fixed width (w-[180px] or auto), do NOT flex-grow
4370
- - On mobile (sm:): search full width, filters wrap to next line
4371
-
4372
- NEVER include marketing sections (hero, pricing, testimonials) on app pages.
4373
- `;
4374
- var DESIGN_QUALITY_AUTH = `
4375
- ## DESIGN QUALITY \u2014 AUTH PAGES
4376
-
4377
- ### Layout
4378
- - Centered card: flex min-h-svh items-center justify-center p-6 md:p-10
4379
- - Card width: w-full max-w-md
4380
- - No navigation, no section containers, no sidebar
4381
- - Single focused form with clear CTA
4382
- - Card \u2192 CardHeader (title + description) \u2192 CardContent (form) \u2192 CardFooter (link to other auth page)
4383
-
4384
- NEVER include navigation bars, sidebars, or multi-section layouts on auth pages.
4385
- `;
4386
- var DESIGN_QUALITY_CRITICAL = `
4387
- ## CRITICAL CODE RULES (violations will be auto-corrected)
4388
- - Every lucide-react icon MUST have className="... shrink-0" to prevent flex squishing
4389
- - Button with asChild wrapping Link: the inner element MUST have className="inline-flex items-center gap-2"
4390
- - NEVER use raw Tailwind colors (bg-blue-500, text-gray-600). ONLY semantic tokens: bg-primary, text-muted-foreground, etc.
4391
- - <Link> and <a> MUST always have an href attribute. Never omit href.
4392
- - CardTitle: NEVER add text-xl, text-2xl, text-lg. CardTitle is text-sm font-medium by default.
4393
- `;
4394
- function getDesignQualityForType(type) {
4395
- switch (type) {
4396
- case "marketing":
4397
- return DESIGN_QUALITY_MARKETING + DESIGN_QUALITY_CRITICAL;
4398
- case "app":
4399
- return DESIGN_QUALITY_APP + DESIGN_QUALITY_CRITICAL;
4400
- case "auth":
4401
- return DESIGN_QUALITY_AUTH + DESIGN_QUALITY_CRITICAL;
4402
- }
4403
- }
4404
- function inferPageTypeFromRoute(route) {
4405
- const slug = route.replace(/^\//, "").split("/")[0] || "";
4406
- const authSlugs = /* @__PURE__ */ new Set([
4407
- "login",
4408
- "register",
4409
- "sign-up",
4410
- "signup",
4411
- "sign-in",
4412
- "signin",
4413
- "forgot-password",
4414
- "reset-password"
4415
- ]);
4416
- const marketingSlugs = /* @__PURE__ */ new Set(["pricing", "features", "about", "blog", "contact", "terms", "privacy"]);
4417
- if (authSlugs.has(slug)) return "auth";
4418
- if (marketingSlugs.has(slug) || slug === "") return "marketing";
4419
- return "app";
4420
- }
4421
- var DESIGN_QUALITY = `${DESIGN_QUALITY_COMMON}
4422
- ${DESIGN_QUALITY_MARKETING}`;
4423
- var VISUAL_DEPTH = `
4424
- ## VISUAL DEPTH TECHNIQUES (pick 1-3 per page based on context)
4425
-
4426
- ### Gradient Techniques
4427
- - Key phrase emphasis: bg-gradient-to-r from-foreground to-foreground/60 bg-clip-text text-transparent
4428
- - Section background: bg-gradient-to-b from-background to-muted/30 (subtle, adds depth)
4429
- - Accent glow: bg-gradient-to-r from-primary/10 via-transparent to-primary/5
4430
-
4431
- ### Depth & Layering
4432
- - Glass cards (landing/hero): bg-card/80 backdrop-blur-sm border-border/40
4433
- - Floating accent blobs: absolute bg-primary/5 blur-3xl rounded-full -z-10 (behind content)
4434
- - Elevated cards on hover: hover:-translate-y-0.5 hover:shadow-md transition-all duration-200
4435
- - Section rhythm: alternate bg-background and bg-muted/5 between sections
4436
-
4437
- ### Micro-interactions (hover/focus only)
4438
- - Card hover lift: hover:-translate-y-0.5 transition-transform duration-200
4439
- - Icon container glow: group-hover:bg-primary/15 transition-colors
4440
- - Button shimmer: relative overflow-hidden + animated pseudo-element on hover
4441
- - Link underline reveal: underline-offset-4 decoration-transparent hover:decoration-foreground transition-all
4442
-
4443
- ### Context Budget (how many techniques to use)
4444
- - Dashboard / Settings / Admin: 0-1 techniques. Clean, functional, fast to scan.
4445
- - Landing / Marketing / Hero: 2-3 techniques. Impressive, memorable, worth scrolling.
4446
- - Product pages (pricing, features, about): 1-2 techniques. Professional with selective wow.
4447
- - Auth pages (login, signup): 0-1 techniques. Trustworthy, focused, minimal.
4448
-
4449
- ### What Makes a Page Memorable
4450
- Ask: "If someone sees this page for 3 seconds, what will they remember?"
4451
- - A landing page \u2192 the hero gradient and headline
4452
- - A dashboard \u2192 the bold stat numbers and clean data density
4453
- - A pricing page \u2192 the highlighted tier standing out from the rest
4454
- - A settings page \u2192 nothing flashy \u2014 that IS the correct answer
4455
- `;
4456
- var RULES_FORMS = `
4457
- FORM RULES:
4458
- - Label above Input (never beside on mobile; beside OK on desktop only for short fields).
4459
- - space-y-2 within field group (Label + Input + optional description).
4460
- - space-y-6 between field groups.
4461
- - CardFooter for form actions (Save, Cancel).
4462
- - Switch for boolean toggles; do NOT use Checkbox for on/off settings.
4463
- - Select for 3+ options; RadioGroup for 2\u20133 options.
4464
- - Two columns on desktop for related fields: md:grid-cols-2. Single column on mobile always.
4465
-
4466
- RADIOGROUP:
4467
- - Use for 2-3 mutually exclusive options. For 4+, use Select.
4468
- - Pattern: <RadioGroup defaultValue="option1"><div className="flex items-center space-x-2"><RadioGroupItem value="option1" id="r1" /><Label htmlFor="r1">Option 1</Label></div></RadioGroup>
4469
- - Vertical layout by default (space-y-2). Horizontal only for 2 options.
4470
- - Label always to the right of the radio, using htmlFor.
4471
-
4472
- FORM VALIDATION (inline errors):
4473
- - Error text: text-sm text-destructive, directly below the input (inside the space-y-2 group).
4474
- - Pattern: <div className="space-y-2"><Label htmlFor="email">Email</Label><Input id="email" className="border-destructive" /><p className="text-sm text-destructive">Please enter a valid email address.</p></div>
4475
- - Show errors after blur or on submit, not on every keystroke.
4476
- - Highlight the field: add border-destructive to the Input.
4477
- - Error summary (form level): <Alert variant="destructive"> at top of form listing all errors.
4478
- - NEVER use toast for form validation. NEVER use alert() or browser dialogs.
4479
-
4480
- MULTI-STEP FORMS / STEPPER:
4481
- - Step indicator: <div className="flex items-center gap-2"> with numbered circles.
4482
- - Active step: bg-primary text-primary-foreground size-8 rounded-full flex items-center justify-center text-sm font-medium.
4483
- - Completed step: same as active but with CheckCircle icon instead of number.
4484
- - Upcoming step: bg-muted text-muted-foreground.
4485
- - Connector between steps: <div className="h-px flex-1 bg-border" /> (horizontal) or <div className="w-px h-8 bg-border mx-auto" /> (vertical).
4486
- - Navigation: "Back" (variant="outline") and "Next"/"Complete" (variant="default") buttons at bottom.
4487
- - Validate current step before allowing Next.
4488
-
4489
- FILE UPLOAD / DROPZONE:
4490
- - Pattern: dashed border area with icon + text. <div className="flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground/25 p-8 text-center hover:border-muted-foreground/50 transition-colors">
4491
- - Icon: <Upload className="size-8 text-muted-foreground mb-2" />
4492
- - Text: <p className="text-sm text-muted-foreground">Drag and drop or <span className="text-foreground underline cursor-pointer">browse</span></p>
4493
- - Accepted formats hint: <p className="text-xs text-muted-foreground mt-1">PNG, JPG up to 10MB</p>
4494
- - Active drag state: border-primary bg-primary/5.
4495
-
4496
- MULTI-SELECT / TAG INPUT:
4497
- - Tags inside input area: <div className="flex flex-wrap gap-1 rounded-md border p-2">
4498
- - Each tag: <Badge variant="secondary" className="gap-1">{name}<X className="size-3 cursor-pointer" /></Badge>
4499
- - Input at the end: <Input className="flex-1 border-0 p-0 focus-visible:ring-0" placeholder="Add..." />
4500
- - Max display: show 5 tags, then "+N more" badge.
4501
- `;
4502
- var RULES_DATA_DISPLAY = `
4503
- DATA DISPLAY RULES:
4504
-
4505
- STAT / METRIC CARDS:
4506
- - Pattern: Card > CardHeader(flex flex-row items-center justify-between space-y-0 pb-2) > CardTitle(text-sm font-medium) + Icon(size-4 text-muted-foreground) ; CardContent > metric(text-2xl font-bold) + change(text-xs text-muted-foreground).
4507
- - Grid: grid gap-4 md:grid-cols-2 lg:grid-cols-4.
4508
- - Trend up: text-emerald-600 (light) / text-emerald-400 (dark) \u2014 exception to semantic-only rule for trend indicators.
4509
- - Trend down: text-destructive.
4510
- - Trend icon: ArrowUp / ArrowDown className="size-3 inline mr-1".
4511
- - No actions on stat cards. Click entire card to drill down (if applicable).
4512
-
4513
- TABLE ROW PATTERNS:
4514
- - Row hover: <TableRow className="hover:bg-muted/50"> on every data row.
4515
- - Action column: last column, right-aligned. Use DropdownMenu with MoreHorizontal icon trigger, NOT inline buttons.
4516
- - Action column header: <TableHead className="w-[50px]"></TableHead> (no label text).
4517
- - Sortable columns: <TableHead className="cursor-pointer select-none"> with ChevronDown/ChevronUp icon, size-4 ml-1.
4518
- - Selected row: bg-muted (single) or checkbox column for multi-select.
4519
- - Responsive: ALWAYS wrap Table in <div className="overflow-x-auto">.
4520
- - Empty table: <TableRow><TableCell colSpan={columns} className="h-24 text-center text-sm text-muted-foreground">No results.</TableCell></TableRow>
4521
-
4522
- PAGINATION:
4523
- - Use shadcn Pagination component. Never build custom.
4524
- - Pattern: Previous + page numbers + Next. Show max 5 page numbers with ellipsis.
4525
- - Placement: below the list/table, centered. <div className="flex justify-center mt-4">
4526
- - For short lists (<20 items): no pagination. For feeds: "Load more" button (variant="outline" className="w-full").
4527
-
4528
- EMPTY STATES:
4529
- - Pattern: <div className="flex flex-col items-center justify-center py-12 text-center">
4530
- - Icon: size-12 text-muted-foreground mb-4 (larger than normal icons \u2014 exception).
4531
- - Title: <h3 className="text-lg font-semibold">No projects yet</h3>
4532
- - Description: <p className="text-sm text-muted-foreground mt-1 max-w-sm">Create your first project to get started.</p>
4533
- - CTA: <Button className="mt-4">Create project</Button>
4534
- - Search empty: "No results for 'query'. Try different keywords." + clear search button.
4535
- - Filtered empty: "No items match your filters." + reset filters button.
4536
-
4537
- DATA FORMATTING:
4538
- - Dates: use relative for recent ("2 hours ago", "Yesterday"), absolute for older ("Jan 26, 2026"). Never ISO format in UI.
4539
- - Numbers: use Intl.NumberFormat or toLocaleString(). 1,234 not 1234. Always include separator for 1000+.
4540
- - Currency: $1,234.56 format. Symbol before number. Two decimal places for amounts.
4541
- - Percentages: one decimal max. "+12.5%" with sign for changes.
4542
-
4543
- STATUS INDICATORS (dot + text):
4544
- - Pattern: <div className="flex items-center gap-2"><div className="size-2 rounded-full bg-emerald-500" /><span className="text-sm">Active</span></div>
4545
- - Colors: bg-emerald-500 (active/online), bg-destructive (error/offline), bg-yellow-500 (warning), bg-muted-foreground (inactive).
4546
- - Alternative: use Badge variants for status in tables/lists (preferred over dots).
4547
-
4548
- TREND INDICATORS:
4549
- - Up (positive): <span className="text-sm text-emerald-600 flex items-center"><ArrowUp className="size-3 mr-1" />12.5%</span>
4550
- - Down (negative): <span className="text-sm text-destructive flex items-center"><ArrowDown className="size-3 mr-1" />3.2%</span>
4551
- - Neutral: <span className="text-sm text-muted-foreground">0%</span>
4552
- - Always include arrow icon + sign (+ or -) + percentage.
4553
-
4554
- TIMELINE / ACTIVITY LOG:
4555
- - Vertical layout: <div className="space-y-4"> with left border.
4556
- - Each entry: <div className="flex gap-4"><div className="flex flex-col items-center"><div className="size-2 rounded-full bg-primary" /><div className="flex-1 w-px bg-border" /></div><div className="flex-1 pb-4"><p className="text-sm font-medium">Event title</p><p className="text-xs text-muted-foreground">2 hours ago</p></div></div>
4557
- - Last item: no connector line (remove w-px div).
4558
-
4559
- AVATAR GROUP (stacked):
4560
- - Pattern: <div className="flex -space-x-2"><Avatar className="ring-2 ring-background">...</Avatar>...</div>
4561
- - Max visible: 4 avatars, then <div className="flex size-8 items-center justify-center rounded-full bg-muted text-xs font-medium ring-2 ring-background">+3</div>
4562
- - Size: size-8 for all items in the stack. ring-2 ring-background to create visual separation.
4563
-
4564
- TRUNCATION:
4565
- - Single line: className="truncate" (overflow-hidden text-ellipsis whitespace-nowrap).
4566
- - Multi-line: className="line-clamp-2" (or line-clamp-3). Needs Tailwind plugin or native CSS.
4567
- - When to truncate: card descriptions (2 lines), table cells (single line), list item subtitles (1-2 lines).
4568
- - Always set title={fullText} for accessibility on truncated text.
4569
-
4570
- SEARCH INPUT:
4571
- - Pattern: <div className="relative"><Search className="absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" /><Input placeholder="Search..." className="pl-9" /></div>
4572
- - Placement: top of the list/table it filters, max-w-sm.
4573
- - Clear button: X icon on right when value is not empty.
4574
- - Debounce: 300ms on keystroke. No search button.
4575
- `;
4576
- var RULES_NAVIGATION = `
4577
- NAVIGATION RULES:
4578
-
4579
- NAVIGATION ACTIVE STATE (one pattern only):
4580
- - Sidebar nav: active item gets bg-accent text-accent-foreground font-medium. Inactive: text-muted-foreground hover:text-foreground hover:bg-accent.
4581
- - Top nav: active item gets text-foreground font-medium. Inactive: text-muted-foreground hover:text-foreground. No underline, no bg.
4582
- - Tab nav: use shadcn Tabs \u2014 default active styling.
4583
- - NEVER mix approaches. bg-accent for sidebar, font-weight for top nav.
4584
-
4585
- BREADCRUMB:
4586
- - Use on any page 2+ levels deep in navigation hierarchy.
4587
- - Component: shadcn Breadcrumb. Never build custom.
4588
- - Pattern: <Breadcrumb><BreadcrumbList><BreadcrumbItem><BreadcrumbLink href="/">Home</BreadcrumbLink></BreadcrumbItem><BreadcrumbSeparator /><BreadcrumbItem><BreadcrumbPage>Current</BreadcrumbPage></BreadcrumbItem></BreadcrumbList></Breadcrumb>
4589
- - Current page: text-foreground (no link). Parent pages: text-muted-foreground with hover.
4590
- - Placement: top of page content, before page title.
4591
- - Max items: show first, last, up to 2 middle. Use BreadcrumbEllipsis for deeper paths.
4592
-
4593
- IN-PAGE NAVIGATION (e.g. Settings tabs, Profile sections):
4594
- - For in-page navigation with <= 5 items, use shadcn Tabs (vertical orientation via orientation="vertical").
4595
- - Do NOT use the full Sidebar component for in-page navigation.
4596
- - Tabs variant for settings: left-side vertical tabs with TabsList + TabsContent.
4597
- - Pattern: <Tabs defaultValue="general" orientation="vertical" className="flex gap-6"><TabsList className="flex-col h-auto"><TabsTrigger value="general">General</TabsTrigger></TabsList><TabsContent value="general">...</TabsContent></Tabs>
4598
-
4599
- SIDEBAR LAYOUT:
4600
- - Use shadcn Sidebar component (SidebarProvider, Sidebar, SidebarContent, SidebarMenu, etc.).
4601
- - Desktop: collapsible sidebar + main content. Mobile: Sheet from left triggered by SidebarTrigger.
4602
- - Sidebar structure: SidebarHeader (logo/brand) \u2192 SidebarContent (SidebarGroup with SidebarMenu) \u2192 SidebarFooter (user/settings).
4603
- - Each nav item: <SidebarMenuItem><SidebarMenuButton asChild isActive={active}><Link href="...">Label</Link></SidebarMenuButton></SidebarMenuItem>
4604
- - Active: add bg-accent text-accent-foreground font-medium.
4605
- - Sidebar collapse: hidden on mobile (md:flex), Sheet trigger visible (md:hidden).
4606
-
4607
- RESPONSIVE SIDEBAR:
4608
- - Desktop (md+): sidebar visible, main content offset.
4609
- - Mobile (<md): sidebar hidden, hamburger menu in top bar. Opens Sheet from left with full nav.
4610
- - Trigger: <Button variant="ghost" size="icon" className="md:hidden"><Menu className="size-5" /></Button>
4611
- - Sheet closes on nav item click (route change).
4612
-
4613
- NAVIGATION MENU (top nav with dropdowns):
4614
- - Use shadcn NavigationMenu for top nav with submenus.
4615
- - Max top-level items: 5-7. For more, group under dropdowns.
4616
- - Keep consistent with top nav active state (text-foreground font-medium for active).
4617
- `;
4618
- var RULES_OVERLAYS = `
4619
- OVERLAY / MODAL RULES:
4620
-
4621
- DIALOG / MODAL:
4622
- - Small dialogs (confirm, delete): max-w-sm. One action + one cancel button.
4623
- - Standard dialogs (forms, details): max-w-md (default). Title + content + footer.
4624
- - Large dialogs (complex forms, previews): max-w-lg. Use sparingly.
4625
- - Internal layout: DialogHeader (DialogTitle + DialogDescription) \u2192 content with space-y-4 \u2192 DialogFooter (buttons right-aligned).
4626
- - Footer buttons: cancel on left (variant="outline"), primary action on right.
4627
- - NEVER use Dialog for success messages \u2014 use toast instead.
4628
- - Destructive: primary button is variant="destructive".
4629
-
4630
- CONFIRMATION DIALOG (delete/destructive):
4631
- - Title: action-specific ("Delete project?" not "Are you sure?").
4632
- - Description: explain consequences. "This will permanently delete 'Project Alpha' and all its data. This action cannot be undone."
4633
- - Buttons: <Button variant="outline">Cancel</Button> <Button variant="destructive">Delete project</Button>
4634
- - NEVER auto-close. Wait for explicit user action.
4635
- - Pattern: DialogHeader(DialogTitle + DialogDescription) \u2192 DialogFooter(Cancel + Destructive).
4636
-
4637
- DROPDOWN MENU:
4638
- - Item text: text-sm. Icon before text: size-4 mr-2.
4639
- - Group related items with DropdownMenuSeparator.
4640
- - Destructive item: className="text-destructive" at bottom, separated.
4641
- - NON-DESTRUCTIVE items: NEVER apply text color classes. Use default text-foreground. No text-amber, text-orange, text-yellow on menu items.
4642
- - Keyboard shortcut hint: <DropdownMenuShortcut>\u2318K</DropdownMenuShortcut>.
4643
- - Max items without scroll: 8. For more, use Command palette.
4644
- - Trigger: Button variant="ghost" size="icon" for icon-only, variant="outline" for labeled.
4645
-
4646
- SHEET (SIDE PANEL):
4647
- - Use Sheet for: filters, mobile navigation, detail preview, secondary forms.
4648
- - Use Dialog for: confirmations, focused tasks, blocking actions.
4649
- - Default side: right. Left only for navigation drawers on mobile.
4650
- - Width: default (max-w-sm). Wider: className="w-[400px] sm:w-[540px]". Never full-width.
4651
- - Internal layout: SheetHeader \u2192 ScrollArea for content \u2192 SheetFooter for actions.
4652
- - Mobile nav: Sheet from left, close on route change.
4653
-
4654
- POPOVER vs DROPDOWN vs DIALOG:
4655
- - Popover: small forms (1-3 fields), color pickers, date pickers, filters.
4656
- - DropdownMenu: action lists (Edit, Delete, Share).
4657
- - Dialog: focused tasks that need full attention.
4658
- - RULE: list of clickable items \u2192 DropdownMenu. Interactive controls \u2192 Popover. Complex/blocking \u2192 Dialog.
4659
- - Popover width: min-w-[200px] to max-w-[320px]. Never wider.
4660
-
4661
- TOOLTIP:
4662
- - Use for icon-only buttons and truncated text. NEVER for critical information.
4663
- - Content: text-xs, max one line.
4664
- - Wrap the page or layout in a single <TooltipProvider>.
4665
-
4666
- COMMAND PALETTE:
4667
- - Use shadcn Command (cmdk) for global search + actions. Trigger: \u2318K.
4668
- - Groups: <CommandGroup heading="Actions">, <CommandGroup heading="Pages">.
4669
- - Items: <CommandItem><Icon className="mr-2 size-4" />Label<CommandShortcut>\u2318N</CommandShortcut></CommandItem>
4670
- - Empty: <CommandEmpty>No results found.</CommandEmpty>
4671
- - Use when dropdown menu has 8+ items or app has 5+ pages to navigate.
4672
-
4673
- DRAWER (mobile bottom sheet):
4674
- - Use Drawer (Vaul) as mobile alternative to Dialog. Pulls up from bottom.
4675
- - Use for mobile-only interactions: filters, confirmations, pickers.
4676
- - On desktop: fall back to Dialog or Popover.
4677
- - Handle: visible grab handle at top center.
4678
- `;
4679
- var RULES_FEEDBACK = `
4680
- FEEDBACK & STATUS RULES:
4681
-
4682
- TOAST / NOTIFICATIONS:
4683
- - Use shadcn toast or Sonner. NEVER use browser alert()/confirm().
4684
- - Position: bottom-right (default). Never top-center.
4685
- - Duration: 3-5 seconds for success, persistent (manual dismiss) for errors.
4686
- - Success: toast({ description: "Changes saved" }) \u2014 no title, brief text.
4687
- - Error: toast({ variant: "destructive", title: "Error", description: "Could not save. Try again." }) \u2014 always title + description.
4688
- - Use toast for background actions (save, delete, copy). Inline text for form validation.
4689
- - NEVER use toast for critical info \u2014 use Alert or Dialog instead.
4690
- - Max one toast visible at a time.
4691
-
4692
- ALERT / BANNER:
4693
- - Use shadcn Alert: <Alert><AlertTitle /><AlertDescription /></Alert>.
4694
- - Info: <Alert> (no variant). Error: <Alert variant="destructive">.
4695
- - Icon: AlertCircle for destructive, Info for default.
4696
- - Placement: top of the relevant section, full width.
4697
- - NEVER use Alert for success \u2014 use toast. NOT for form validation (those go inline).
4698
-
4699
- SKELETON / LOADING:
4700
- - Text skeleton: h-4 rounded-md bg-muted animate-pulse. Vary widths: w-full, w-3/4, w-1/2.
4701
- - Card skeleton: <Card><CardHeader><div className="h-4 w-1/2 animate-pulse rounded-md bg-muted" /></CardHeader></Card>
4702
- - Avatar skeleton: <div className="size-8 animate-pulse rounded-full bg-muted" />
4703
- - ALWAYS skeleton matching content shape. NEVER centered spinner for page loads.
4704
- - Spinner (Loader2): only for inline actions. <Loader2 className="size-4 animate-spin" />
4705
- - Button loading: <Button disabled><Loader2 className="mr-2 size-4 animate-spin" />Saving...</Button>
4706
-
4707
- PROGRESS BAR:
4708
- - Use shadcn Progress. Pattern: <Progress value={66} className="h-2" />
4709
- - Label: text-sm above or beside progress bar. Show percentage or "Step 2 of 3".
4710
- - Colors: default (bg-primary) for normal. For status: wrap in div and apply text color context.
4711
- - Use for: file uploads, multi-step processes, quotas. NEVER for page loads (use skeleton).
4712
-
4713
- ERROR PAGES (404, 500):
4714
- - Centered layout: flex min-h-[50vh] flex-col items-center justify-center text-center.
4715
- - 404: <h1 className="text-4xl font-bold">404</h1><p className="text-muted-foreground mt-2">Page not found</p><Button className="mt-4" asChild><Link href="/">Go home</Link></Button>
4716
- - 500: same layout but "Something went wrong" + "Try again" button.
4717
- - NEVER leave error page without a CTA. Always provide a way back.
4718
-
4719
- NOTIFICATION INDICATORS:
4720
- - Unread dot on nav icon: <div className="relative"><Bell className="size-4" /><div className="absolute -top-1 -right-1 size-2 rounded-full bg-destructive" /></div>
4721
- - Unread count badge: <div className="absolute -top-1.5 -right-1.5 flex size-4 items-center justify-center rounded-full bg-destructive text-[10px] font-medium text-destructive-foreground">3</div>
4722
- - Max display: "9+" for counts above 9.
4723
- - Position: always top-right of the icon. Use relative + absolute positioning.
4724
-
4725
- COPY TO CLIPBOARD:
4726
- - Button: <Button variant="ghost" size="sm" className="h-7 px-2 text-xs">Copy</Button>
4727
- - Feedback: swap icon from Copy to Check for 2 seconds, then revert.
4728
- - Pattern: onClick \u2192 navigator.clipboard.writeText(text) \u2192 setIcon("check") \u2192 setTimeout 2000 \u2192 setIcon("copy").
4729
- - Toast optional: only for non-obvious copies (e.g. API key). Not needed for code blocks.
4730
- `;
4731
- var RULES_CONTENT = `
4732
- CONTENT PAGE RULES:
4733
-
4734
- PRICING CARDS:
4735
- - Grid: grid gap-6 md:grid-cols-3. Highlighted tier: ring-2 ring-primary.
4736
- - Card structure: CardHeader(tier name + price) \u2192 CardContent(feature list) \u2192 CardFooter(CTA).
4737
- - Price: <div className="text-3xl font-bold">$29<span className="text-sm font-normal text-muted-foreground">/month</span></div>
4738
- - Features: <ul className="space-y-2 text-sm"><li className="flex items-center gap-2"><Check className="size-4 text-primary" />Feature</li></ul>
4739
- - Popular badge: <Badge className="absolute -top-3 left-1/2 -translate-x-1/2">Popular</Badge> on the Card (relative positioning).
4740
- - CTA: primary variant on highlighted tier, outline on others.
4741
-
4742
- PRICE DISPLAY (with discount):
4743
- - Old price: <span className="text-sm text-muted-foreground line-through">$49</span>
4744
- - New price: <span className="text-2xl font-bold">$29</span>
4745
- - Discount badge: <Badge variant="secondary">Save 40%</Badge> beside price.
4746
- - Always show both prices when discount is active.
4747
-
4748
- HERO SECTION:
4749
- - Full width, centered text: <section className="flex flex-col items-center text-center py-16 md:py-24 gap-4">
4750
- - Headline: <h1 className="text-3xl md:text-5xl font-bold tracking-tight max-w-3xl">
4751
- - Subheadline: <p className="text-lg text-muted-foreground max-w-2xl">
4752
- - CTAs: <div className="flex gap-3"><Button size="lg">Primary</Button><Button variant="outline" size="lg">Secondary</Button></div>
4753
- - NEVER use text-6xl or larger. Max headline size: text-5xl on desktop.
4754
-
4755
- FEATURE GRID:
4756
- - Grid: grid gap-6 md:grid-cols-3. Each feature: Card or plain div.
4757
- - Structure: Icon (size-8 text-primary mb-2) \u2192 title (text-sm font-semibold) \u2192 description (text-sm text-muted-foreground).
4758
- - Icon: in a muted circle: <div className="flex size-10 items-center justify-center rounded-lg bg-muted"><Icon className="size-5 text-primary" /></div>
4759
-
4760
- TESTIMONIAL CARDS:
4761
- - Card with: quote (text-sm italic), author name (text-sm font-medium), role (text-xs text-muted-foreground), avatar (size-8).
4762
- - Author section: <div className="flex items-center gap-3 mt-4"><Avatar>...</Avatar><div><p className="text-sm font-medium">Name</p><p className="text-xs text-muted-foreground">Title, Company</p></div></div>
4763
- - Quote marks: optional, use text-muted-foreground opacity-50.
4764
-
4765
- LANDING PAGE SECTIONS:
4766
- - Section spacing: py-16 md:py-24. Between sections: no extra gap (padding handles it).
4767
- - Section container: max-w-6xl mx-auto px-4.
4768
- - Section title: text-2xl md:text-3xl font-bold tracking-tight text-center mb-4.
4769
- - Section subtitle: text-muted-foreground text-center max-w-2xl mx-auto mb-8.
4770
- - Alternating layout: consider alternate background (bg-muted/50) every other section.
4771
-
4772
- CHANGELOG / RELEASE NOTES:
4773
- - Each version: <div className="space-y-2"><div className="flex items-center gap-2"><Badge variant="outline">v2.1.0</Badge><span className="text-xs text-muted-foreground">Jan 26, 2026</span></div><ul className="space-y-1 text-sm pl-4">...</ul></div>
4774
- - Categories: use Badge variant to differentiate (default=New, secondary=Improved, destructive=Fixed).
4775
- `;
4776
- var RULES_CARDS_LAYOUT = `
4777
- CARD & LAYOUT RULES:
4778
-
4779
- COMPONENT PATTERNS:
4780
- - Card shadow: NONE or shadow-sm. NEVER shadow-md/lg/xl.
4781
- - CardHeader for stat card: className="flex flex-row items-center justify-between space-y-0 pb-2"
4782
- - NO nested cards (card inside card). Max 2 levels: Card > content.
4783
-
4784
- BADGE VARIANT MAPPING (consistent status colors):
4785
- - Success/active: <Badge variant="default">Active</Badge> (also: Paid, Verified, Online, Published)
4786
- - Neutral/info: <Badge variant="secondary">Pending</Badge> (also: Draft, In Progress, Scheduled)
4787
- - Attention/warning: <Badge variant="outline">Review</Badge> (also: Expiring, Low Stock)
4788
- - Error/destructive: <Badge variant="destructive">Failed</Badge> (also: Overdue, Declined, Cancelled)
4789
- - RULE: same semantic status = same Badge variant across ALL pages.
4790
-
4791
- AVATAR STYLING:
4792
- - Default size: size-8. Profile headers: size-10. Never larger. Shape: always rounded-full.
4793
- - Fallback: text-xs font-medium, bg-muted text-muted-foreground.
4794
- - Always use shadcn Avatar: <Avatar><AvatarImage /><AvatarFallback>JD</AvatarFallback></Avatar>
4795
-
4796
- SECTION HEADERS:
4797
- - Standard: <div className="flex items-center justify-between"><h2 className="text-lg font-semibold tracking-tight">Title</h2><Button variant="outline" size="sm">Action</Button></div>
4798
- - With description: add <p className="text-sm text-muted-foreground"> below h2, wrap in <div className="space-y-1">.
4799
- - NEVER use h3/h4 for top-level sections. h2 for sections, h3 for sub-sections.
4800
-
4801
- BUTTON GROUPING & PLACEMENT:
4802
- - Multiple buttons: <div className="flex items-center gap-2">
4803
- - Order: secondary (outline/ghost) FIRST, primary LAST. Destructive always last.
4804
- - Page-level: <div className="flex items-center justify-between"> (title left, actions right).
4805
- - Card footer: <CardFooter className="flex justify-end gap-2">
4806
- - Dialog footer: <DialogFooter> \u2014 cancel then primary.
4807
- - Icon + text: <Button><Plus className="mr-2 size-4" />Add Item</Button>
4808
- - Icon-only: <Button variant="ghost" size="icon"> \u2014 always with Tooltip.
4809
-
4810
- CARD ACTION PLACEMENT:
4811
- - Content cards: DropdownMenu with MoreHorizontal in top-right of CardHeader.
4812
- - Form cards: actions in CardFooter (Save, Cancel).
4813
- - Feature/marketing cards: single CTA button at bottom.
4814
- - Card with link: wrap in <Link> or onClick. Add hover:bg-accent/50 transition-colors.
4815
- - NEVER actions in BOTH CardHeader AND CardFooter.
4816
-
4817
- SEPARATOR / DIVIDER:
4818
- - Between page sections: <Separator className="my-6" />.
4819
- - Between items in list: border-b on each item (className="border-b last:border-0 py-3"). NOT Separator.
4820
- - Between groups in DropdownMenu: <DropdownMenuSeparator />.
4821
- - NEVER use native <hr>. NEVER use divide-y.
4822
-
4823
- TABS STYLING:
4824
- - Use shadcn Tabs. Never build custom tab UI.
4825
- - TabsContent: pt-4. Standalone: TabsList w-full md:w-auto. Max tabs visible: 5.
4826
-
4827
- MAX-WIDTH CONTAINER:
4828
- - App pages with sidebar: no container needed (sidebar + main handles width).
4829
- - App pages without sidebar: main content max-w-4xl mx-auto.
4830
- - Landing/marketing pages: max-w-6xl mx-auto px-4.
4831
- - NEVER use container class inside app layouts \u2014 only for standalone pages.
4832
-
4833
- SETTINGS PAGE LAYOUT:
4834
- - Two-column on desktop: left nav (w-48) + right content area. Single column on mobile.
4835
- - Left nav: list of text links, vertical. Active: font-medium text-foreground. Inactive: text-muted-foreground.
4836
- - Content area: Card for each settings section with CardHeader + CardContent + CardFooter.
4837
- - Danger zone: separate Card at bottom with destructive styling.
4838
-
4839
- DASHBOARD GRID:
4840
- - Top row: stats (grid gap-4 md:grid-cols-2 lg:grid-cols-4).
4841
- - Middle: primary content (table, chart area). Full width or 2/3 + 1/3 split.
4842
- - Bottom: secondary content (recent activity, quick actions).
4843
- - Pattern: <main className="flex flex-1 flex-col gap-4 p-4 lg:p-6">
4844
- `;
4845
- var RULES_SHADCN_APIS = `
4846
- SHADCN COMPONENT API REFERENCE (use these exact patterns):
4847
-
4848
- SIDEBAR:
4849
- - Wrap in <SidebarProvider>. Components: Sidebar, SidebarContent, SidebarHeader, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarTrigger.
4850
- - Nav items: <SidebarMenuItem><SidebarMenuButton asChild isActive={active}><Link href="...">Label</Link></SidebarMenuButton></SidebarMenuItem>
4851
- - NEVER use Button for sidebar nav \u2192 use SidebarMenuButton.
4852
-
4853
- SELECT (Radix compound component):
4854
- - Pattern: <Select><SelectTrigger><SelectValue placeholder="..." /></SelectTrigger><SelectContent><SelectItem value="x">X</SelectItem></SelectContent></Select>
4855
- - NEVER use native <select>. Always use shadcn Select.
4856
-
4857
- DROPDOWN MENU:
4858
- - Pattern: <DropdownMenu><DropdownMenuTrigger asChild><Button>Open</Button></DropdownMenuTrigger><DropdownMenuContent><DropdownMenuItem>Action</DropdownMenuItem></DropdownMenuContent></DropdownMenu>
4859
- - Destructive items: className="text-destructive focus:text-destructive"
4860
- - NEVER nest <button> inside trigger \u2192 use asChild.
4861
-
4862
- SHEET (mobile panels, sidebars):
4863
- - Pattern: <Sheet><SheetTrigger asChild><Button>Open</Button></SheetTrigger><SheetContent side="right">...</SheetContent></Sheet>
4864
- - side: "top" | "right" | "bottom" | "left". Default "right".
4865
-
4866
- DIALOG:
4867
- - Pattern: <Dialog><DialogTrigger asChild><Button>Open</Button></DialogTrigger><DialogContent><DialogHeader><DialogTitle>Title</DialogTitle><DialogDescription>Desc</DialogDescription></DialogHeader>...</DialogContent></Dialog>
4868
- - ALWAYS include DialogTitle for accessibility.
4869
-
4870
- COMMAND (command palette / search):
4871
- - Pattern: <Command><CommandInput placeholder="Search..." /><CommandList><CommandEmpty>No results</CommandEmpty><CommandGroup heading="Suggestions"><CommandItem>Item</CommandItem></CommandGroup></CommandList></Command>
4872
-
4873
- ANTI-PATTERNS (NEVER DO):
4874
- - NEVER use <button> for sidebar navigation \u2192 SidebarMenuButton
4875
- - NEVER use native <select> \u2192 shadcn Select
4876
- - NEVER nest <button> inside a trigger \u2192 use asChild prop
4877
- - NEVER use custom dropdown \u2192 shadcn DropdownMenu
4878
- - NEVER build custom modal \u2192 shadcn Dialog
4879
- - NEVER use custom toast \u2192 shadcn Sonner (toast())
4880
- `;
4881
- var RULES_COMPONENTS_MISC = `
4882
- MISCELLANEOUS COMPONENT RULES:
4883
-
4884
- ACCORDION:
4885
- - Use shadcn Accordion. Never build custom collapsible.
4886
- - Type: "single" for FAQ (one open at a time). "multiple" for settings/filters.
4887
- - Trigger text: text-sm font-medium. Content: text-sm text-muted-foreground.
4888
- - In Card: no border on AccordionItem (Card provides border). Standalone: built-in border-b.
4889
-
4890
- SCROLLAREA:
4891
- - Use shadcn ScrollArea when content height is known and fixed (sidebar, dropdown, modal body).
4892
- - Use native overflow-y-auto for dynamic page content.
4893
- - Sidebar: <ScrollArea className="h-[calc(100vh-4rem)]">
4894
- - Dialog: <ScrollArea className="max-h-[60vh]"> for tall content.
4895
-
4896
- CODE BLOCK / MONOSPACE:
4897
- - Inline: <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-sm">code</code>
4898
- - Block: <div className="rounded-md bg-muted px-4 py-3 font-mono text-sm">command</div>
4899
- - Copy button: <Button variant="ghost" size="sm" className="h-7 px-2 text-xs">Copy</Button> \u2014 always same style.
4900
-
4901
- IMAGE / MEDIA CONTAINERS:
4902
- - Aspect ratio: aspect-video (16:9) for hero. aspect-square for avatars/thumbnails.
4903
- - Rounded: rounded-xl for hero. rounded-md for inline. rounded-full for avatars.
4904
- - Fallback: bg-muted with centered icon.
4905
- - Object fit: object-cover for photos. object-contain for logos.
4906
-
4907
- CALENDAR / DATE PICKER:
4908
- - Use shadcn Calendar for date selection. Pair with Popover for date picker trigger.
4909
- - Display format: "Jan 26, 2026" in the trigger. Never raw ISO.
4910
- - Placeholder: "Pick a date".
4911
-
4912
- TOGGLE / TOGGLEGROUP:
4913
- - Use for view switchers (grid/list, map/satellite). Not for boolean settings (use Switch).
4914
- - Pattern: <ToggleGroup type="single" value={view} onValueChange={setView}><ToggleGroupItem value="grid"><Grid className="size-4" /></ToggleGroupItem><ToggleGroupItem value="list"><List className="size-4" /></ToggleGroupItem></ToggleGroup>
4915
- - Size: default. Variant: outline.
4916
-
4917
- DARK MODE TOGGLE:
4918
- - Pattern: <Button variant="ghost" size="icon" onClick={toggleTheme}><Sun className="size-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /><Moon className="absolute size-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /></Button>
4919
- - Placement: top-right of navbar, or inside settings.
4920
-
4921
- RATING / STARS:
4922
- - Pattern: 5 star icons. Filled: <Star className="size-4 fill-primary text-primary" />. Empty: <Star className="size-4 text-muted-foreground" />.
4923
- - Display only (non-interactive): no hover states needed.
4924
- - Interactive: add hover:text-primary cursor-pointer on each star.
4925
-
4926
- Z-INDEX HIERARCHY:
4927
- - Content: z-0 (default). Sticky headers: z-10. Dropdowns/Popovers: z-50. Sheet/Dialog overlay: z-50 (shadcn default). Toast: z-[100].
4928
- - NEVER use arbitrary z-index values above z-50 except for toast (z-[100]).
4929
-
4930
- ANIMATION / TRANSITIONS:
4931
- - Default transition: transition-colors for color changes. transition-all for size/position.
4932
- - Duration: 150ms (Tailwind default) for hover effects. 200-300ms for enter/exit animations.
4933
- - Easing: ease-in-out for most. ease-out for enter. ease-in for exit.
4934
- - NEVER animate on page load (no entrance animations). Animate only on user interaction.
4935
- - Allowed: hover effects, accordion open/close, dialog enter/exit, dropdown appear, toast slide in.
4936
- - BANNED: bouncing elements, parallax, auto-playing carousels, decorative animations that delay content.
4937
- `;
4938
- var INTERACTION_PATTERNS = `
4939
- ## INTERACTION PATTERNS (mandatory)
4940
-
4941
- ### Loading & Latency
4942
- - NEVER show empty screen while loading. Always: skeleton OR spinner OR progress bar
4943
- - For operations >1s: show what's happening ("Saving changes...", "Loading dashboard...")
4944
- - For operations >3s: show progress or steps ("Step 2 of 3: Generating layout...")
4945
- - After completion: confirm success with brief feedback ("Changes saved" or toast/banner)
4946
- - Skeleton > spinner for page loads. Spinner > skeleton for inline actions (button submit)
4947
-
4948
- ### Feedback & Confirmation
4949
- - Every user action gets visible feedback:
4950
- - Button click \u2192 disabled state + loading indicator during processing
4951
- - Form submit \u2192 "Saving..." \u2192 "Saved \u2713" (or error message)
4952
- - Destructive action \u2192 confirmation dialog BEFORE execution, never after
4953
- - Toggle/switch \u2192 immediate visual change (optimistic UI)
4954
- - Success feedback: subtle (toast, inline text). Don't use modals for success.
4955
- - Error feedback: prominent, inline near the cause, with suggested fix
4956
-
4957
- ### Error Recovery
4958
- - Error messages: what happened + why + what to do next
4959
- \u2717 "Something went wrong"
4960
- \u2713 "Could not save changes \u2014 connection lost. Your changes are preserved. Try again."
4961
- - Always provide an action: "Try again", "Go back", "Contact support"
4962
- - For form errors: highlight specific fields, don't clear the form
4963
- - For page-level errors: show error boundary with retry button
4964
- - Never dead-end the user \u2014 every error state has a way out
4965
-
4966
- ### Empty States
4967
- - Every list, table, grid, feed MUST handle zero items:
4968
- - Friendly message (not "No data" \u2014 instead "No projects yet")
4969
- - Primary action ("Create your first project")
4970
- - Optional illustration or icon
4971
- - Search with no results: "No results for 'X'. Try different keywords." + clear search button
4972
- - Filtered with no results: "No items match your filters." + reset filters button
4973
-
4974
- ### Navigation & Transitions
4975
- - Current page clearly indicated in nav (active state)
4976
- - Page transitions: no jarring jumps. Content should appear smoothly
4977
- - Back navigation: always available on detail/child pages
4978
- - Breadcrumbs on pages 2+ levels deep
4979
- - After destructive action (delete): redirect to parent list, not empty detail page
4980
-
4981
- ### Handoff Patterns
4982
- - Data entered in one context must persist when moving to another
4983
- - "Unsaved changes" warning when navigating away from dirty form
4984
- - Copy/export actions: confirm what was copied/exported ("Copied to clipboard \u2713")
4985
- - External links: open in new tab, never navigate away without warning
4986
- `;
4987
- var CONTEXTUAL_CATEGORIES = [
4988
- {
4989
- keywords: /form|input|login|signup|sign.?up|register|settings|profile|password|email|field|validation|upload|stepper|step|wizard|radio|tag.?input|multi.?select/i,
4990
- rules: RULES_FORMS
4991
- },
4992
- {
4993
- keywords: /dashboard|table|list|stats|chart|data|analytics|metric|activity|timeline|report|pagination|paginate|search|filter|sort|empty.?state/i,
4994
- rules: RULES_DATA_DISPLAY
4995
- },
4996
- {
4997
- keywords: /nav|sidebar|menu|breadcrumb|header|footer|navigation|mobile.?menu|hamburger/i,
4998
- rules: RULES_NAVIGATION
4999
- },
5000
- {
5001
- keywords: /modal|dialog|dropdown|sheet|popover|confirm|delete|toast|notification|alert|error|loading|skeleton|progress|overlay|command.?palette|drawer/i,
5002
- rules: RULES_OVERLAYS
5003
- },
5004
- {
5005
- keywords: /modal|dialog|dropdown|sheet|popover|confirm|toast|notification|alert|error|loading|skeleton|progress|copy|clipboard/i,
5006
- rules: RULES_FEEDBACK
5007
- },
5008
- {
5009
- keywords: /landing|pricing|about|blog|testimonial|hero|feature|changelog|marketing|homepage|home.?page|price|plan|tier/i,
5010
- rules: RULES_CONTENT
5011
- },
5012
- {
5013
- keywords: /card|grid|layout|dashboard|badge|avatar|tab|section|separator|button|setting|stat|page/i,
5014
- rules: RULES_CARDS_LAYOUT
5015
- },
5016
- {
5017
- keywords: /accordion|scroll|code|image|calendar|date|toggle|dark.?mode|theme|rating|star|animation|z.?index/i,
5018
- rules: RULES_COMPONENTS_MISC
5019
- },
5020
- {
5021
- keywords: /sidebar|select|dropdown|sheet|dialog|modal|command|trigger|asChild|menu/i,
5022
- rules: RULES_SHADCN_APIS
5023
- }
5024
- ];
5025
- function selectContextualRules(message) {
5026
- const matched = /* @__PURE__ */ new Set();
5027
- for (const category of CONTEXTUAL_CATEGORIES) {
5028
- if (category.keywords.test(message)) {
5029
- matched.add(category.rules);
5030
- }
5031
- }
5032
- if (matched.size === 0) {
5033
- return "";
5034
- }
5035
- return [...matched].join("\n");
5036
- }
5037
- var DESIGN_CONSTRAINTS = `${DESIGN_THINKING}
5038
- ${CORE_CONSTRAINTS}
5039
- ${DESIGN_QUALITY}
5040
- ${VISUAL_DEPTH}
5041
- ${RULES_FORMS}
5042
- ${RULES_DATA_DISPLAY}
5043
- ${RULES_NAVIGATION}
5044
- ${RULES_OVERLAYS}
5045
- ${RULES_FEEDBACK}
5046
- ${RULES_CONTENT}
5047
- ${RULES_CARDS_LAYOUT}
5048
- ${RULES_COMPONENTS_MISC}`;
5049
-
5050
4173
  // src/agents/modifier.ts
5051
4174
  async function parseModification(message, context, provider = "auto", options) {
5052
4175
  const ai = await createAIProvider(provider);
@@ -6949,6 +6072,18 @@ ${selectImport}`
6949
6072
  fixed = fixedByRules;
6950
6073
  fixes.push(...ruleFixes);
6951
6074
  }
6075
+ const beforeTabsFix = fixed;
6076
+ fixed = fixed.replace(
6077
+ /(<TabsTrigger\b[^>]*className=")([^"]*)(")/g,
6078
+ (_m, pre, classes, post) => {
6079
+ const cleaned = classes.replace(/\b(border-input|border\b|outline\b)\s*/g, "").trim();
6080
+ if (cleaned !== classes.trim()) return `${pre}${cleaned}${post}`;
6081
+ return _m;
6082
+ }
6083
+ );
6084
+ if (fixed !== beforeTabsFix) {
6085
+ fixes.push("stripped border from TabsTrigger (shadcn handles active state)");
6086
+ }
6952
6087
  fixed = fixed.replace(/className="([^"]*)"/g, (_match, inner) => {
6953
6088
  const cleaned = inner.replace(/\s{2,}/g, " ").trim();
6954
6089
  return `className="${cleaned}"`;
@@ -8056,7 +7191,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
8056
7191
  if (plan && plan.sharedComponents.length > 0) {
8057
7192
  spinner.start(`Phase 4.5/6 \u2014 Generating ${plan.sharedComponents.length} shared components from plan...`);
8058
7193
  try {
8059
- const { generateSharedComponentsFromPlan } = await import("./plan-generator-Q5DUGYPD.js");
7194
+ const { generateSharedComponentsFromPlan } = await import("./plan-generator-FHD7TXD5.js");
8060
7195
  const generated = await generateSharedComponentsFromPlan(
8061
7196
  plan,
8062
7197
  styleContext,
@@ -8112,7 +7247,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
8112
7247
  const isAuth = isAuthRoute(route) || isAuthRoute(name);
8113
7248
  const pageType = plan ? getPageType(route, plan) : inferPageTypeFromRoute(route);
8114
7249
  const designConstraints = getDesignQualityForType(pageType);
8115
- const authNote = isAuth ? 'For this auth page: use centered card layout with outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10" and inner div className="w-full max-w-md". Do NOT use section containers or full-width wrappers. The auth layout provides centering \u2014 just output the card content.' : void 0;
7250
+ const authNote = isAuth ? 'For this auth page: the auth layout already provides centering (flex items-center justify-center min-h-svh). Do NOT add your own centering wrapper or min-h-svh. Just output a div with className="w-full max-w-md" containing the Card. Do NOT use section containers or full-width wrappers.' : void 0;
8116
7251
  const prompt = [
8117
7252
  `Create ONE page called "${name}" at route "${route}".`,
8118
7253
  `Context: ${message}.`,