@cronus-ui/stack 0.6.0

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.
@@ -0,0 +1,826 @@
1
+ /**
2
+ * The Cronus Stack Builder taxonomy.
3
+ *
4
+ * Coherent, robust, and CORRECT — every cross-category rule below is encoded on
5
+ * the options themselves (`requires` / `conflicts` / `implies` / `recommends`)
6
+ * so the pure resolver in `engine.ts` can enforce them deterministically.
7
+ *
8
+ * Conventions:
9
+ * - Option ids are GLOBALLY UNIQUE and prefixed by category, e.g. "orm-drizzle".
10
+ * - The FIRST option in each "single" category is its default (and is always a
11
+ * safe, dependency-free choice so cascades can always fall back to it).
12
+ * - Icons are lucide-react names.
13
+ */
14
+ // --- React-capable web frontends (used by UI-library `requires`). ----------
15
+ const REACT_WEB = ["web-next", "web-tanstack-start", "web-tanstack-router", "web-react-router"];
16
+ // --- SQL databases (used by ORM / DB-setup constraints). -------------------
17
+ const SQL_DBS = ["db-sqlite", "db-postgres", "db-mysql"];
18
+ // --- Dedicated backend servers (conflict with fullstack meta-frameworks). --
19
+ const DEDICATED_BACKENDS = ["backend-hono", "backend-elysia", "backend-express", "backend-fastify"];
20
+ export const catalog = [
21
+ // ------------------------------------------------------------------ WEB ---
22
+ {
23
+ id: "web",
24
+ title: "Web Frontend",
25
+ description: "The web client framework.",
26
+ kind: "single",
27
+ options: [
28
+ { id: "web-none", name: "None", description: "No web frontend.", icon: "circle-slash" },
29
+ {
30
+ id: "web-next",
31
+ name: "Next.js",
32
+ description: "React App Router meta-framework.",
33
+ icon: "triangle",
34
+ },
35
+ {
36
+ id: "web-tanstack-start",
37
+ name: "TanStack Start",
38
+ description: "Full-stack React framework on TanStack Router.",
39
+ icon: "layers",
40
+ },
41
+ {
42
+ id: "web-tanstack-router",
43
+ name: "TanStack Router",
44
+ description: "Type-safe SPA router.",
45
+ icon: "route",
46
+ },
47
+ {
48
+ id: "web-react-router",
49
+ name: "React Router",
50
+ description: "React Router framework mode.",
51
+ icon: "git-fork",
52
+ },
53
+ { id: "web-nuxt", name: "Nuxt", description: "Vue meta-framework.", icon: "mountain" },
54
+ { id: "web-svelte", name: "Svelte", description: "SvelteKit app framework.", icon: "flame" },
55
+ { id: "web-solid", name: "Solid", description: "SolidStart app framework.", icon: "atom" },
56
+ {
57
+ id: "web-astro",
58
+ name: "Astro",
59
+ description: "Content-first islands framework.",
60
+ icon: "rocket",
61
+ },
62
+ ],
63
+ },
64
+ // -------------------------------------------------------------- BACKEND ---
65
+ {
66
+ id: "backend",
67
+ title: "Backend",
68
+ description: "The server framework that hosts your API.",
69
+ kind: "single",
70
+ options: [
71
+ {
72
+ id: "backend-none",
73
+ name: "None",
74
+ description: "No dedicated backend.",
75
+ icon: "circle-slash",
76
+ },
77
+ {
78
+ id: "backend-fullstack-next",
79
+ name: "Fullstack Next",
80
+ description: "Use Next.js server (route handlers) as the backend.",
81
+ icon: "triangle",
82
+ // Only meaningful with a Next web app, and replaces a separate backend/runtime.
83
+ requires: ["web-next"],
84
+ conflicts: [...DEDICATED_BACKENDS, "backend-convex"],
85
+ },
86
+ {
87
+ id: "backend-fullstack-tanstack",
88
+ name: "Fullstack TanStack Start",
89
+ description: "Use TanStack Start server functions as the backend.",
90
+ icon: "layers",
91
+ requires: ["web-tanstack-start"],
92
+ conflicts: [...DEDICATED_BACKENDS, "backend-convex"],
93
+ },
94
+ {
95
+ id: "backend-hono",
96
+ name: "Hono",
97
+ description: "Ultrafast edge-ready web framework.",
98
+ icon: "flame",
99
+ },
100
+ {
101
+ id: "backend-elysia",
102
+ name: "Elysia",
103
+ description: "Bun-native, end-to-end typed framework.",
104
+ icon: "feather",
105
+ requires: ["runtime-bun"],
106
+ },
107
+ {
108
+ id: "backend-express",
109
+ name: "Express",
110
+ description: "Classic Node.js web framework.",
111
+ icon: "server",
112
+ requires: ["runtime-node"],
113
+ conflicts: ["runtime-cloudflare"],
114
+ },
115
+ {
116
+ id: "backend-fastify",
117
+ name: "Fastify",
118
+ description: "Fast, low-overhead Node framework.",
119
+ icon: "zap",
120
+ },
121
+ {
122
+ id: "backend-convex",
123
+ name: "Convex",
124
+ description: "All-in-one reactive backend (DB + functions).",
125
+ icon: "box",
126
+ badge: "beta",
127
+ // BaaS owns its own data layer + runtime.
128
+ conflicts: [
129
+ "db-sqlite",
130
+ "db-postgres",
131
+ "db-mysql",
132
+ "db-mongodb",
133
+ "orm-drizzle",
134
+ "orm-prisma",
135
+ "orm-mongoose",
136
+ ],
137
+ },
138
+ ],
139
+ },
140
+ // -------------------------------------------------------------- RUNTIME ---
141
+ {
142
+ id: "runtime",
143
+ title: "Runtime",
144
+ description: "Where the server code executes.",
145
+ kind: "single",
146
+ options: [
147
+ {
148
+ id: "runtime-bun",
149
+ name: "Bun",
150
+ description: "All-in-one JS runtime & toolkit.",
151
+ icon: "rabbit",
152
+ },
153
+ {
154
+ id: "runtime-node",
155
+ name: "Node.js",
156
+ description: "The standard JS runtime.",
157
+ icon: "hexagon",
158
+ },
159
+ {
160
+ id: "runtime-cloudflare",
161
+ name: "Cloudflare Workers",
162
+ description: "Edge runtime on the Cloudflare network.",
163
+ icon: "cloud",
164
+ },
165
+ {
166
+ id: "runtime-none",
167
+ name: "None",
168
+ description: "No standalone runtime.",
169
+ icon: "circle-slash",
170
+ },
171
+ ],
172
+ },
173
+ // ------------------------------------------------------------------ API ---
174
+ {
175
+ id: "api",
176
+ title: "API",
177
+ description: "Type-safe client/server contract.",
178
+ kind: "single",
179
+ options: [
180
+ { id: "api-none", name: "None", description: "No typed API layer.", icon: "circle-slash" },
181
+ { id: "api-trpc", name: "tRPC", description: "End-to-end typesafe RPC.", icon: "plug" },
182
+ {
183
+ id: "api-orpc",
184
+ name: "oRPC",
185
+ description: "OpenAPI-compatible typesafe RPC.",
186
+ icon: "plug-zap",
187
+ badge: "new",
188
+ },
189
+ ],
190
+ },
191
+ // ------------------------------------------------------------- DATABASE ---
192
+ {
193
+ id: "database",
194
+ title: "Database",
195
+ description: "Your primary data store.",
196
+ kind: "single",
197
+ options: [
198
+ { id: "db-none", name: "None", description: "No database.", icon: "circle-slash" },
199
+ { id: "db-sqlite", name: "SQLite", description: "Embedded SQL database.", icon: "database" },
200
+ {
201
+ id: "db-postgres",
202
+ name: "PostgreSQL",
203
+ description: "Advanced open-source SQL.",
204
+ icon: "database",
205
+ },
206
+ { id: "db-mysql", name: "MySQL", description: "Popular open-source SQL.", icon: "database" },
207
+ { id: "db-mongodb", name: "MongoDB", description: "Document-oriented NoSQL.", icon: "leaf" },
208
+ ],
209
+ },
210
+ // ------------------------------------------------------------------ ORM ---
211
+ {
212
+ id: "orm",
213
+ title: "ORM",
214
+ description: "How you talk to the database.",
215
+ kind: "single",
216
+ options: [
217
+ {
218
+ id: "orm-none",
219
+ name: "None",
220
+ description: "No ORM / query builder.",
221
+ icon: "circle-slash",
222
+ },
223
+ {
224
+ id: "orm-drizzle",
225
+ name: "Drizzle",
226
+ description: "Type-safe SQL query builder & ORM.",
227
+ icon: "droplets",
228
+ // SQL-only in this catalog: needs a SQL db, never Mongo.
229
+ requires: ["db-sql"],
230
+ conflicts: ["db-mongodb"],
231
+ },
232
+ {
233
+ id: "orm-prisma",
234
+ name: "Prisma",
235
+ description: "Schema-first ORM with migrations.",
236
+ icon: "triangle",
237
+ requires: ["db-sql"],
238
+ conflicts: ["db-mongodb"],
239
+ },
240
+ {
241
+ id: "orm-mongoose",
242
+ name: "Mongoose",
243
+ description: "MongoDB object modeling.",
244
+ icon: "leaf",
245
+ requires: ["db-mongodb"],
246
+ conflicts: ["db-sqlite", "db-postgres", "db-mysql"],
247
+ },
248
+ ],
249
+ },
250
+ // ------------------------------------------------------------- DB SETUP ---
251
+ {
252
+ id: "dbSetup",
253
+ title: "DB Setup",
254
+ description: "Hosted provider / local setup for the database.",
255
+ kind: "single",
256
+ options: [
257
+ {
258
+ id: "dbsetup-basic",
259
+ name: "Basic",
260
+ description: "Plain local setup, no provider.",
261
+ icon: "settings",
262
+ },
263
+ {
264
+ id: "dbsetup-turso",
265
+ name: "Turso",
266
+ description: "Hosted libSQL (SQLite) edge DB.",
267
+ icon: "globe",
268
+ requires: ["db-sqlite"],
269
+ },
270
+ {
271
+ id: "dbsetup-neon",
272
+ name: "Neon",
273
+ description: "Serverless PostgreSQL.",
274
+ icon: "globe",
275
+ requires: ["db-postgres"],
276
+ },
277
+ {
278
+ id: "dbsetup-supabase",
279
+ name: "Supabase",
280
+ description: "Postgres platform with auth/storage.",
281
+ icon: "globe",
282
+ requires: ["db-postgres"],
283
+ },
284
+ {
285
+ id: "dbsetup-planetscale",
286
+ name: "PlanetScale",
287
+ description: "Serverless MySQL / Postgres.",
288
+ icon: "globe",
289
+ // Available for either Postgres OR MySQL.
290
+ requires: ["db-sql-server"],
291
+ conflicts: ["db-sqlite", "db-mongodb"],
292
+ },
293
+ {
294
+ id: "dbsetup-d1",
295
+ name: "Cloudflare D1",
296
+ description: "Cloudflare's serverless SQLite.",
297
+ icon: "cloud",
298
+ requires: ["db-sqlite"],
299
+ },
300
+ {
301
+ id: "dbsetup-atlas",
302
+ name: "MongoDB Atlas",
303
+ description: "Hosted MongoDB cluster.",
304
+ icon: "leaf",
305
+ requires: ["db-mongodb"],
306
+ },
307
+ ],
308
+ },
309
+ // ----------------------------------------------------------------- AUTH ---
310
+ {
311
+ id: "auth",
312
+ title: "Auth",
313
+ description: "Authentication strategy.",
314
+ kind: "single",
315
+ options: [
316
+ { id: "auth-none", name: "None", description: "No auth.", icon: "circle-slash" },
317
+ {
318
+ id: "auth-better-auth",
319
+ name: "Better-Auth",
320
+ description: "Framework-agnostic, ownable auth.",
321
+ icon: "shield-check",
322
+ },
323
+ {
324
+ id: "auth-clerk",
325
+ name: "Clerk",
326
+ description: "Hosted auth & user management.",
327
+ icon: "shield",
328
+ badge: "gated",
329
+ },
330
+ ],
331
+ },
332
+ // ------------------------------------------------------------- PAYMENTS ---
333
+ {
334
+ id: "payments",
335
+ title: "Payments",
336
+ description: "Billing & monetization.",
337
+ kind: "single",
338
+ optional: true,
339
+ options: [
340
+ { id: "pay-none", name: "None", description: "No payments.", icon: "circle-slash" },
341
+ {
342
+ id: "pay-polar",
343
+ name: "Polar",
344
+ description: "Merchant of record for devs.",
345
+ icon: "circle-dollar-sign",
346
+ badge: "new",
347
+ },
348
+ {
349
+ id: "pay-stripe",
350
+ name: "Stripe",
351
+ description: "The standard payments platform.",
352
+ icon: "credit-card",
353
+ },
354
+ ],
355
+ },
356
+ // ------------------------------------------------------------- UI LIBRARY -
357
+ {
358
+ id: "ui",
359
+ title: "UI Library",
360
+ description: "Component system for the frontend.",
361
+ kind: "single",
362
+ options: [
363
+ {
364
+ id: "ui-cronus",
365
+ name: "Cronus UI",
366
+ description: "Product UI system: compose + live theme + copy-in you can upgrade.",
367
+ icon: "sparkles",
368
+ requires: ["web-react"],
369
+ recommends: ["mcp-cronus-ui"],
370
+ },
371
+ {
372
+ id: "ui-shadcn",
373
+ name: "shadcn/ui",
374
+ description: "Copy-in Radix + Tailwind components.",
375
+ icon: "component",
376
+ requires: ["web-react"],
377
+ },
378
+ {
379
+ id: "ui-heroui",
380
+ name: "HeroUI",
381
+ description: "Beautiful React component library.",
382
+ icon: "component",
383
+ requires: ["web-react"],
384
+ },
385
+ {
386
+ id: "ui-aceternity",
387
+ name: "Aceternity",
388
+ description: "Animated React UI components.",
389
+ icon: "wand-sparkles",
390
+ requires: ["web-react"],
391
+ badge: "experimental",
392
+ },
393
+ {
394
+ id: "ui-tailwind",
395
+ name: "Tailwind-only",
396
+ description: "Utility CSS, bring your own components.",
397
+ icon: "paintbrush",
398
+ },
399
+ { id: "ui-none", name: "None", description: "No UI library.", icon: "circle-slash" },
400
+ ],
401
+ },
402
+ // ------------------------------------------------------- AI ASSISTANTS ----
403
+ {
404
+ id: "assistants",
405
+ title: "AI Assistant",
406
+ description: "Coding agents wired into the repo.",
407
+ kind: "multi",
408
+ options: [
409
+ {
410
+ id: "ai-claude-code",
411
+ name: "Claude Code",
412
+ description: "Anthropic's official coding agent.",
413
+ icon: "bot",
414
+ },
415
+ {
416
+ id: "ai-cursor",
417
+ name: "Cursor",
418
+ description: "AI-first code editor.",
419
+ icon: "mouse-pointer-2",
420
+ },
421
+ { id: "ai-windsurf", name: "Windsurf", description: "Agentic IDE by Codeium.", icon: "wind" },
422
+ { id: "ai-copilot", name: "Copilot", description: "GitHub Copilot.", icon: "github" },
423
+ {
424
+ id: "ai-cline",
425
+ name: "Cline",
426
+ description: "Autonomous coding agent for VS Code.",
427
+ icon: "terminal",
428
+ },
429
+ ],
430
+ },
431
+ // ---------------------------------------------------------- MCP SERVERS ----
432
+ {
433
+ id: "mcp",
434
+ title: "MCP Servers",
435
+ description: "Model Context Protocol servers available to agents.",
436
+ kind: "multi",
437
+ options: [
438
+ {
439
+ id: "mcp-cronus-ui",
440
+ name: "cronus-ui",
441
+ description: "Cronus UI component & token context.",
442
+ icon: "sparkles",
443
+ recommends: ["ui-cronus"],
444
+ },
445
+ {
446
+ id: "mcp-postgres",
447
+ name: "postgres",
448
+ description: "Query & inspect your database.",
449
+ icon: "database",
450
+ },
451
+ {
452
+ id: "mcp-playwright",
453
+ name: "playwright",
454
+ description: "Drive a real browser for testing.",
455
+ icon: "globe",
456
+ },
457
+ {
458
+ id: "mcp-github",
459
+ name: "github",
460
+ description: "Issues, PRs, and repo context.",
461
+ icon: "github",
462
+ },
463
+ {
464
+ id: "mcp-sentry",
465
+ name: "sentry",
466
+ description: "Error & performance telemetry.",
467
+ icon: "siren",
468
+ },
469
+ ],
470
+ },
471
+ // --------------------------------------------------------------- SKILLS ----
472
+ {
473
+ id: "skills",
474
+ title: "Skills",
475
+ description: "Reusable agent skill packs to install.",
476
+ kind: "multi",
477
+ options: [
478
+ {
479
+ id: "skill-frontend",
480
+ name: "frontend",
481
+ description: "Frontend & component patterns.",
482
+ icon: "layout",
483
+ },
484
+ {
485
+ id: "skill-db",
486
+ name: "db",
487
+ description: "Schema, migrations, and queries.",
488
+ icon: "database",
489
+ },
490
+ {
491
+ id: "skill-security-review",
492
+ name: "security-review",
493
+ description: "Adversarial security review.",
494
+ icon: "shield-alert",
495
+ },
496
+ {
497
+ id: "skill-a11y",
498
+ name: "a11y",
499
+ description: "Accessibility auditing & fixes.",
500
+ icon: "accessibility",
501
+ },
502
+ {
503
+ id: "skill-testing",
504
+ name: "testing",
505
+ description: "Unit, integration & e2e testing.",
506
+ icon: "flask-conical",
507
+ },
508
+ ],
509
+ },
510
+ // ------------------------------------------------------------ VIBE MODE ----
511
+ {
512
+ id: "vibe",
513
+ title: "Vibe Mode",
514
+ description: "Looser guardrails, faster iteration for prototyping.",
515
+ kind: "toggle",
516
+ options: [],
517
+ },
518
+ // --------------------------------------------------------------- DEPLOY ----
519
+ {
520
+ id: "deploy",
521
+ title: "Deploy",
522
+ description: "Where the app ships.",
523
+ kind: "single",
524
+ optional: true,
525
+ options: [
526
+ {
527
+ id: "deploy-none",
528
+ name: "None",
529
+ description: "No deploy target configured.",
530
+ icon: "circle-slash",
531
+ },
532
+ {
533
+ id: "deploy-vercel",
534
+ name: "Vercel",
535
+ description: "Zero-config frontend cloud.",
536
+ icon: "triangle",
537
+ },
538
+ {
539
+ id: "deploy-cloudflare",
540
+ name: "Cloudflare",
541
+ description: "Deploy to the Cloudflare edge.",
542
+ icon: "cloud",
543
+ requires: ["runtime-cloudflare"],
544
+ },
545
+ {
546
+ id: "deploy-docker",
547
+ name: "Docker",
548
+ description: "Containerized deploy anywhere.",
549
+ icon: "container",
550
+ },
551
+ {
552
+ id: "deploy-fly",
553
+ name: "Fly.io",
554
+ description: "Run app servers near users.",
555
+ icon: "plane",
556
+ },
557
+ ],
558
+ },
559
+ // ------------------------------------------------------- PACKAGE MANAGER ---
560
+ {
561
+ id: "packageManager",
562
+ title: "Package Manager",
563
+ description: "Dependency & workspace tool.",
564
+ kind: "single",
565
+ options: [
566
+ { id: "pm-bun", name: "bun", description: "Fast all-in-one toolkit.", icon: "rabbit" },
567
+ {
568
+ id: "pm-pnpm",
569
+ name: "pnpm",
570
+ description: "Efficient, strict node_modules.",
571
+ icon: "package",
572
+ },
573
+ {
574
+ id: "pm-npm",
575
+ name: "npm",
576
+ description: "The default Node package manager.",
577
+ icon: "package",
578
+ },
579
+ ],
580
+ },
581
+ // --------------------------------------------------------------- ADDONS ---
582
+ {
583
+ id: "addons",
584
+ title: "Addons",
585
+ description: "Optional tooling & capabilities.",
586
+ kind: "multi",
587
+ options: [
588
+ {
589
+ id: "addon-pwa",
590
+ name: "PWA",
591
+ description: "Installable, offline-capable app.",
592
+ icon: "smartphone",
593
+ },
594
+ {
595
+ id: "addon-tauri",
596
+ name: "Tauri",
597
+ description: "Native desktop app shell.",
598
+ icon: "app-window",
599
+ badge: "experimental",
600
+ },
601
+ { id: "addon-biome", name: "Biome", description: "Fast formatter & linter.", icon: "wand" },
602
+ {
603
+ id: "addon-turborepo",
604
+ name: "Turborepo",
605
+ description: "Monorepo task runner & cache.",
606
+ icon: "git-merge",
607
+ },
608
+ {
609
+ id: "addon-husky",
610
+ name: "Husky/Lefthook",
611
+ description: "Git hooks for quality gates.",
612
+ icon: "dog",
613
+ },
614
+ {
615
+ id: "addon-starlight",
616
+ name: "Starlight",
617
+ description: "Docs site (Astro Starlight).",
618
+ icon: "book-open",
619
+ },
620
+ ],
621
+ },
622
+ // ------------------------------------------------------------------ GIT ---
623
+ {
624
+ id: "git",
625
+ title: "Git",
626
+ description: "Initialize a git repository.",
627
+ kind: "toggle",
628
+ options: [],
629
+ },
630
+ // --------------------------------------------------------- INSTALL DEPS ---
631
+ {
632
+ id: "install",
633
+ title: "Install deps",
634
+ description: "Run the package manager install after scaffolding.",
635
+ kind: "toggle",
636
+ options: [],
637
+ },
638
+ // ---------------------------------------------------------- CONVENTIONS ---
639
+ // Project standards baked into the KICKOFF brief so generated code stays
640
+ // consistent from the first commit. These are simple, self-evident choices, so
641
+ // they render as compact segmented pickers (layout: "segmented") rather than
642
+ // icon cards. The first option in each is the recommended best-practice default.
643
+ {
644
+ id: "naming",
645
+ title: "File naming",
646
+ description: "How files and folders are cased.",
647
+ kind: "single",
648
+ layout: "segmented",
649
+ options: [
650
+ {
651
+ id: "naming-kebab",
652
+ name: "kebab-case",
653
+ description: "user-profile.tsx",
654
+ icon: "case-sensitive",
655
+ },
656
+ {
657
+ id: "naming-camel",
658
+ name: "camelCase",
659
+ description: "userProfile.tsx",
660
+ icon: "case-sensitive",
661
+ },
662
+ {
663
+ id: "naming-pascal",
664
+ name: "PascalCase",
665
+ description: "UserProfile.tsx",
666
+ icon: "case-sensitive",
667
+ },
668
+ {
669
+ id: "naming-snake",
670
+ name: "snake_case",
671
+ description: "user_profile.tsx",
672
+ icon: "case-sensitive",
673
+ },
674
+ ],
675
+ },
676
+ {
677
+ id: "structure",
678
+ title: "Directory structure",
679
+ description: "Where application code lives.",
680
+ kind: "single",
681
+ layout: "segmented",
682
+ options: [
683
+ {
684
+ id: "structure-src",
685
+ name: "src/ directory",
686
+ description: "All app code under src/.",
687
+ icon: "folder-tree",
688
+ },
689
+ {
690
+ id: "structure-root",
691
+ name: "Root-level",
692
+ description: "app/ and code at the repo root.",
693
+ icon: "folder",
694
+ },
695
+ ],
696
+ },
697
+ {
698
+ id: "importAlias",
699
+ title: "Import paths",
700
+ description: "How modules reference each other.",
701
+ kind: "single",
702
+ layout: "segmented",
703
+ options: [
704
+ {
705
+ id: "import-alias",
706
+ name: "@/ alias",
707
+ description: "Absolute imports from the app root.",
708
+ icon: "at-sign",
709
+ },
710
+ {
711
+ id: "import-relative",
712
+ name: "Relative",
713
+ description: "Relative ./ and ../ paths.",
714
+ icon: "route",
715
+ },
716
+ ],
717
+ },
718
+ {
719
+ id: "commitStyle",
720
+ title: "Commits",
721
+ description: "Commit message convention.",
722
+ kind: "single",
723
+ layout: "segmented",
724
+ options: [
725
+ {
726
+ id: "commit-conventional",
727
+ name: "Conventional",
728
+ description: "type(scope): subject",
729
+ icon: "git-commit",
730
+ },
731
+ {
732
+ id: "commit-plain",
733
+ name: "Plain",
734
+ description: "Freeform commit messages.",
735
+ icon: "git-commit",
736
+ },
737
+ ],
738
+ },
739
+ {
740
+ id: "tsStrict",
741
+ title: "TypeScript",
742
+ description: "Type-checking strictness.",
743
+ kind: "single",
744
+ layout: "segmented",
745
+ options: [
746
+ {
747
+ id: "ts-strict",
748
+ name: "Strict",
749
+ description: "strict + no implicit any.",
750
+ icon: "shield-check",
751
+ },
752
+ {
753
+ id: "ts-standard",
754
+ name: "Standard",
755
+ description: "Default tsconfig strictness.",
756
+ icon: "shield",
757
+ },
758
+ ],
759
+ },
760
+ ];
761
+ /**
762
+ * Virtual / synthetic option ids used only inside `requires`/`conflicts` to
763
+ * express GROUP constraints the resolver expands against the real selection:
764
+ * - "web-react" → any of the React-capable web frontends is selected.
765
+ * - "db-sql" → any SQL database is selected.
766
+ * - "db-sql-server" → Postgres or MySQL is selected (PlanetScale).
767
+ *
768
+ * Keeping these out of the catalog options keeps the UI clean while still
769
+ * letting constraints reference logical groups.
770
+ */
771
+ export const SYNTHETIC_REQUIREMENTS = {
772
+ "web-react": REACT_WEB,
773
+ "db-sql": SQL_DBS,
774
+ "db-sql-server": ["db-postgres", "db-mysql"],
775
+ };
776
+ /** Toggle categories that default to ON. */
777
+ export const TOGGLE_DEFAULTS_ON = new Set(["git", "install"]);
778
+ /** Multi categories that default to a preselected set. */
779
+ export const MULTI_DEFAULTS = {
780
+ assistants: ["ai-claude-code"],
781
+ };
782
+ /** Re-exported convenience groups (also consumed by tests). */
783
+ export const GROUPS = { REACT_WEB, SQL_DBS, DEDICATED_BACKENDS };
784
+ /**
785
+ * The builder section each category renders under. Assigned to `category.group`
786
+ * at module load so the catalog stays the single source of truth; the builder
787
+ * reads `group` + {@link GROUP_ORDER} to lay the page out in labeled sections.
788
+ */
789
+ const CATEGORY_GROUP = {
790
+ web: "Framework",
791
+ backend: "Framework",
792
+ runtime: "Framework",
793
+ api: "Framework",
794
+ database: "Data",
795
+ orm: "Data",
796
+ dbSetup: "Data",
797
+ auth: "Product",
798
+ payments: "Product",
799
+ ui: "Product",
800
+ assistants: "AI & agents",
801
+ mcp: "AI & agents",
802
+ skills: "AI & agents",
803
+ vibe: "AI & agents",
804
+ naming: "Conventions",
805
+ structure: "Conventions",
806
+ importAlias: "Conventions",
807
+ commitStyle: "Conventions",
808
+ tsStrict: "Conventions",
809
+ deploy: "Tooling",
810
+ packageManager: "Tooling",
811
+ addons: "Tooling",
812
+ git: "Tooling",
813
+ install: "Tooling",
814
+ };
815
+ /** The fixed order builder sections render in (empty sections are skipped). */
816
+ export const GROUP_ORDER = [
817
+ "Framework",
818
+ "Data",
819
+ "Product",
820
+ "AI & agents",
821
+ "Conventions",
822
+ "Tooling",
823
+ ];
824
+ for (const cat of catalog)
825
+ cat.group = CATEGORY_GROUP[cat.id];
826
+ //# sourceMappingURL=catalog.js.map