@withmata/blueprints 0.3.5 → 0.5.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.
Files changed (62) hide show
  1. package/.claude/skills/audit/SKILL.md +4 -4
  2. package/.claude/skills/blueprint-catalog/SKILL.md +17 -7
  3. package/.claude/skills/copywrite/SKILL.md +187 -0
  4. package/.claude/skills/copywrite-landing/SKILL.md +489 -0
  5. package/.claude/skills/design-system/SKILL.md +970 -0
  6. package/.claude/skills/new-project/SKILL.md +168 -112
  7. package/.claude/skills/scaffold-auth/SKILL.md +9 -9
  8. package/.claude/skills/scaffold-db/SKILL.md +14 -14
  9. package/.claude/skills/scaffold-env/SKILL.md +4 -4
  10. package/.claude/skills/scaffold-foundation/SKILL.md +15 -15
  11. package/.claude/skills/scaffold-tailwind/SKILL.md +17 -3
  12. package/.claude/skills/scaffold-ui/SKILL.md +155 -36
  13. package/ENGINEERING.md +2 -2
  14. package/blueprints/discovery/design-system/BLUEPRINT.md +1479 -0
  15. package/blueprints/discovery/marketing-copywriting/BLUEPRINT.md +664 -0
  16. package/blueprints/features/auth-better-auth/BLUEPRINT.md +20 -22
  17. package/blueprints/features/db-drizzle-postgres/BLUEPRINT.md +12 -12
  18. package/blueprints/features/db-drizzle-postgres/files/db/src/example-entity.ts +1 -1
  19. package/blueprints/features/db-drizzle-postgres/files/db/src/scripts/seed.ts +1 -1
  20. package/blueprints/features/env-t3/BLUEPRINT.md +1 -1
  21. package/blueprints/features/tailwind-v4/BLUEPRINT.md +9 -2
  22. package/blueprints/features/tailwind-v4/files/tailwind-config/shared-styles.css +80 -1
  23. package/blueprints/features/ui-shared-components/BLUEPRINT.md +411 -78
  24. package/blueprints/features/ui-shared-components/files/ui/components/ui/alert-dialog.tsx +192 -0
  25. package/blueprints/features/ui-shared-components/files/ui/components/ui/avatar.tsx +71 -0
  26. package/blueprints/features/ui-shared-components/files/ui/components/ui/badge.tsx +52 -0
  27. package/blueprints/features/ui-shared-components/files/ui/components/ui/breadcrumb.tsx +122 -0
  28. package/blueprints/features/ui-shared-components/files/ui/components/ui/button.tsx +56 -0
  29. package/blueprints/features/ui-shared-components/files/ui/components/ui/card-select.tsx +72 -0
  30. package/blueprints/features/ui-shared-components/files/ui/components/ui/card.tsx +100 -0
  31. package/blueprints/features/ui-shared-components/files/ui/components/ui/collapsible.tsx +34 -0
  32. package/blueprints/features/ui-shared-components/files/ui/components/ui/combobox.tsx +301 -0
  33. package/blueprints/features/ui-shared-components/files/ui/components/ui/dropdown-menu.tsx +264 -0
  34. package/blueprints/features/ui-shared-components/files/ui/components/ui/empty-state.tsx +43 -0
  35. package/blueprints/features/ui-shared-components/files/ui/components/ui/entity-select.tsx +110 -0
  36. package/blueprints/features/ui-shared-components/files/ui/components/ui/field.tsx +237 -0
  37. package/blueprints/features/ui-shared-components/files/ui/components/ui/form-field.tsx +217 -0
  38. package/blueprints/features/ui-shared-components/files/ui/components/ui/input-group.tsx +161 -0
  39. package/blueprints/features/ui-shared-components/files/ui/components/ui/input.tsx +20 -0
  40. package/blueprints/features/ui-shared-components/files/ui/components/ui/label.tsx +20 -0
  41. package/blueprints/features/ui-shared-components/files/ui/components/ui/org-switcher.tsx +114 -0
  42. package/blueprints/features/ui-shared-components/files/ui/components/ui/page-header.tsx +45 -0
  43. package/blueprints/features/ui-shared-components/files/ui/components/ui/pagination.tsx +52 -0
  44. package/blueprints/features/ui-shared-components/files/ui/components/ui/pill-select.tsx +151 -0
  45. package/blueprints/features/ui-shared-components/files/ui/components/ui/popover.tsx +41 -0
  46. package/blueprints/features/ui-shared-components/files/ui/components/ui/search-input.tsx +49 -0
  47. package/blueprints/features/ui-shared-components/files/ui/components/ui/select.tsx +205 -0
  48. package/blueprints/features/ui-shared-components/files/ui/components/ui/selected-entity-card.tsx +47 -0
  49. package/blueprints/features/ui-shared-components/files/ui/components/ui/separator.tsx +25 -0
  50. package/blueprints/features/ui-shared-components/files/ui/components/ui/sidebar.tsx +389 -0
  51. package/blueprints/features/ui-shared-components/files/ui/components/ui/status-filter.tsx +43 -0
  52. package/blueprints/features/ui-shared-components/files/ui/components/ui/tag-input.tsx +131 -0
  53. package/blueprints/features/ui-shared-components/files/ui/components/ui/textarea.tsx +18 -0
  54. package/blueprints/features/ui-shared-components/files/ui/components/ui/user-menu.tsx +149 -0
  55. package/blueprints/features/ui-shared-components/files/ui/components.json +11 -8
  56. package/blueprints/features/ui-shared-components/files/ui/package.json +20 -11
  57. package/blueprints/foundation/monorepo-turbo/BLUEPRINT.md +19 -20
  58. package/blueprints/foundation/monorepo-turbo/files/root/package.json +1 -1
  59. package/dist/index.js +27 -10
  60. package/package.json +1 -1
  61. package/blueprints/features/tailwind-v4/files/tailwind-config/package.json +0 -20
  62. package/blueprints/foundation/monorepo-turbo/files/root/pnpm-workspace.yaml +0 -5
@@ -0,0 +1,131 @@
1
+ "use client";
2
+
3
+ import { Button } from "#components/ui/button";
4
+ import { cn } from "#utils/cn";
5
+ import { PlusIcon, X } from "@phosphor-icons/react";
6
+ import { type KeyboardEvent, useRef, useState } from "react";
7
+
8
+ export interface TagInputProps {
9
+ value: string[];
10
+ onChange: (value: string[]) => void;
11
+ maxItems: number;
12
+ placeholder?: string;
13
+ disabled?: boolean;
14
+ className?: string;
15
+ hideCounter?: boolean;
16
+ }
17
+
18
+ export function TagInput({
19
+ value,
20
+ onChange,
21
+ maxItems,
22
+ placeholder = "Type and press Enter...",
23
+ disabled = false,
24
+ className,
25
+ hideCounter = false,
26
+ }: TagInputProps) {
27
+ const [inputValue, setInputValue] = useState("");
28
+ const inputRef = useRef<HTMLInputElement>(null);
29
+
30
+ const isAtMax = value.length >= maxItems;
31
+
32
+ const addTag = () => {
33
+ const trimmed = inputValue.trim();
34
+ if (!trimmed || value.length >= maxItems) return;
35
+
36
+ // Check for duplicates (case-insensitive)
37
+ if (value.some((v) => v.toLowerCase() === trimmed.toLowerCase())) {
38
+ setInputValue("");
39
+ return;
40
+ }
41
+
42
+ onChange([...value, trimmed]);
43
+ setInputValue("");
44
+ inputRef.current?.focus();
45
+ };
46
+
47
+ const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
48
+ if (e.key === "Enter" && inputValue.trim()) {
49
+ e.preventDefault();
50
+ addTag();
51
+ }
52
+ };
53
+
54
+ // Handle removing a tag
55
+ const handleRemove = (indexToRemove: number) => {
56
+ onChange(value.filter((_, index) => index !== indexToRemove));
57
+ };
58
+
59
+ return (
60
+ <div className={cn("space-y-2", className)}>
61
+ {/* Input field */}
62
+ {!isAtMax && (
63
+ <div
64
+ className={cn(
65
+ "bg-input/30 border-input focus-within:border-primary/90 flex min-h-9 items-center gap-1.5 rounded-4xl border bg-clip-padding px-2.5 py-1.5 text-sm transition-colors",
66
+ disabled && "opacity-60 cursor-not-allowed",
67
+ )}
68
+ >
69
+ <input
70
+ ref={inputRef}
71
+ type="text"
72
+ value={inputValue}
73
+ onChange={(e) => setInputValue(e.target.value)}
74
+ onKeyDown={handleKeyDown}
75
+ placeholder={value.length === 0 ? placeholder : "Add another..."}
76
+ disabled={disabled}
77
+ className="min-w-16 flex-1 outline-none bg-transparent"
78
+ />
79
+ {inputValue.trim() && (
80
+ <button
81
+ type="button"
82
+ onClick={addTag}
83
+ disabled={disabled}
84
+ className="flex items-center gap-0.5 shrink-0 rounded-full bg-primary/10 text-primary px-2 py-0.5 text-xs font-medium hover:bg-primary/20 transition-colors"
85
+ >
86
+ <PlusIcon className="size-3" weight="bold" />
87
+ Add
88
+ </button>
89
+ )}
90
+ </div>
91
+ )}
92
+
93
+ {/* Tags */}
94
+ {value.length > 0 && (
95
+ <div className="flex flex-wrap gap-1.5">
96
+ {value.map((tag, index) => (
97
+ <div
98
+ key={`${tag}-${index}`}
99
+ className="bg-muted-foreground/10 text-foreground flex h-7 w-fit items-center justify-center gap-1 rounded-4xl px-2.5 pr-0.5 text-sm font-medium whitespace-nowrap"
100
+ >
101
+ {tag}
102
+ <Button
103
+ type="button"
104
+ variant="ghost"
105
+ size="icon-xs"
106
+ aria-label={`Remove ${tag}`}
107
+ onClick={() => handleRemove(index)}
108
+ disabled={disabled}
109
+ className="-ml-1 opacity-50 hover:opacity-100"
110
+ >
111
+ <X className="pointer-events-none size-3" />
112
+ </Button>
113
+ </div>
114
+ ))}
115
+ </div>
116
+ )}
117
+
118
+ {/* Counter */}
119
+ {!hideCounter && (
120
+ <p
121
+ className={cn(
122
+ "text-xs text-muted-foreground",
123
+ isAtMax && "text-destructive font-medium",
124
+ )}
125
+ >
126
+ {value.length}/{maxItems} items{isAtMax && " (max)"}
127
+ </p>
128
+ )}
129
+ </div>
130
+ );
131
+ }
@@ -0,0 +1,18 @@
1
+ import type * as React from "react";
2
+
3
+ import { cn } from "#utils/cn";
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "border-input bg-input/30 focus-visible:border-primary/90 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none rounded-xl border px-3 py-2 text-base transition-colors md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ export { Textarea };
@@ -0,0 +1,149 @@
1
+ "use client";
2
+
3
+ import {
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuGroup,
7
+ DropdownMenuItem,
8
+ DropdownMenuSeparator,
9
+ DropdownMenuTrigger,
10
+ } from "#components/ui/dropdown-menu";
11
+ import {
12
+ SidebarMenu,
13
+ SidebarMenuButton,
14
+ SidebarMenuItem,
15
+ useSidebar,
16
+ } from "#components/ui/sidebar";
17
+ import { Avatar } from "#components/ui/avatar";
18
+ import { cn } from "#utils/cn";
19
+ import { CaretUpDownIcon } from "@phosphor-icons/react/CaretUpDown";
20
+ import { GearIcon } from "@phosphor-icons/react/Gear";
21
+ import { SignOutIcon } from "@phosphor-icons/react/SignOut";
22
+ import { UserIcon } from "@phosphor-icons/react/User";
23
+ import type * as React from "react";
24
+
25
+ export interface UserMenuUser {
26
+ name: string;
27
+ email: string;
28
+ image?: string | null;
29
+ }
30
+
31
+ export interface UserMenuItem {
32
+ label: string;
33
+ icon: React.ReactNode;
34
+ onClick: () => void;
35
+ }
36
+
37
+ export interface UserMenuProps {
38
+ user: UserMenuUser | null;
39
+ isLoading?: boolean;
40
+ items?: UserMenuItem[];
41
+ onSignOut?: () => void;
42
+ onSettingsClick?: () => void;
43
+ onProfileClick?: () => void;
44
+ className?: string;
45
+ }
46
+
47
+ export function UserMenu({
48
+ user,
49
+ isLoading = false,
50
+ items,
51
+ onSignOut,
52
+ onSettingsClick,
53
+ onProfileClick,
54
+ className,
55
+ }: UserMenuProps) {
56
+ const { state } = useSidebar();
57
+ const isCollapsed = state === "collapsed";
58
+
59
+ if (isLoading) {
60
+ return (
61
+ <SidebarMenu>
62
+ <SidebarMenuItem>
63
+ <SidebarMenuButton size="lg" className="animate-pulse">
64
+ <div className="size-8 rounded-lg bg-sidebar-accent" />
65
+ {!isCollapsed && (
66
+ <div className="flex-1 space-y-1">
67
+ <div className="h-3 w-20 rounded bg-sidebar-accent" />
68
+ <div className="h-2 w-24 rounded bg-sidebar-accent" />
69
+ </div>
70
+ )}
71
+ </SidebarMenuButton>
72
+ </SidebarMenuItem>
73
+ </SidebarMenu>
74
+ );
75
+ }
76
+
77
+ if (!user) return null;
78
+
79
+ return (
80
+ <SidebarMenu className={cn(className)}>
81
+ <SidebarMenuItem>
82
+ <DropdownMenu>
83
+ <DropdownMenuTrigger
84
+ render={
85
+ <SidebarMenuButton
86
+ size="lg"
87
+ className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
88
+ >
89
+ <Avatar
90
+ name={user.name}
91
+ image={user.image}
92
+ size="default"
93
+ className="bg-sidebar-primary text-sidebar-primary-foreground"
94
+ />
95
+ {!isCollapsed && (
96
+ <>
97
+ <div className="grid flex-1 text-left text-sm leading-tight overflow-hidden">
98
+ <span className="truncate font-semibold">
99
+ {user.name}
100
+ </span>
101
+ <span className="truncate text-xs text-sidebar-foreground/70">
102
+ {user.email}
103
+ </span>
104
+ </div>
105
+ <CaretUpDownIcon className="ml-auto size-4 shrink-0" />
106
+ </>
107
+ )}
108
+ </SidebarMenuButton>
109
+ }
110
+ />
111
+ <DropdownMenuContent
112
+ side={isCollapsed ? "right" : "top"}
113
+ align="start"
114
+ >
115
+ <DropdownMenuGroup>
116
+ {onProfileClick && (
117
+ <DropdownMenuItem onClick={onProfileClick}>
118
+ <UserIcon className="size-4" />
119
+ <span>Profile</span>
120
+ </DropdownMenuItem>
121
+ )}
122
+ {onSettingsClick && (
123
+ <DropdownMenuItem onClick={onSettingsClick}>
124
+ <GearIcon className="size-4" />
125
+ <span>Settings</span>
126
+ </DropdownMenuItem>
127
+ )}
128
+ {items?.map((item) => (
129
+ <DropdownMenuItem key={item.label} onClick={item.onClick}>
130
+ {item.icon}
131
+ <span>{item.label}</span>
132
+ </DropdownMenuItem>
133
+ ))}
134
+ </DropdownMenuGroup>
135
+ {onSignOut && (
136
+ <>
137
+ <DropdownMenuSeparator />
138
+ <DropdownMenuItem onClick={onSignOut}>
139
+ <SignOutIcon className="size-4" />
140
+ <span>Sign out</span>
141
+ </DropdownMenuItem>
142
+ </>
143
+ )}
144
+ </DropdownMenuContent>
145
+ </DropdownMenu>
146
+ </SidebarMenuItem>
147
+ </SidebarMenu>
148
+ );
149
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://ui.shadcn.com/schema.json",
3
- "style": "new-york",
3
+ "style": "base-maia",
4
4
  "rsc": true,
5
5
  "tsx": true,
6
6
  "tailwind": {
@@ -10,12 +10,15 @@
10
10
  "cssVariables": true,
11
11
  "prefix": ""
12
12
  },
13
- "iconLibrary": "lucide",
13
+ "iconLibrary": "phosphor",
14
14
  "aliases": {
15
- "components": "#components",
16
- "utils": "#utils",
17
- "ui": "#components/ui",
18
- "lib": "#utils",
19
- "hooks": "#hooks"
20
- }
15
+ "components": "components",
16
+ "utils": "utils",
17
+ "ui": "components/ui",
18
+ "lib": "utils",
19
+ "hooks": "hooks"
20
+ },
21
+ "menuColor": "default",
22
+ "menuAccent": "subtle",
23
+ "registries": {}
21
24
  }
@@ -3,33 +3,42 @@
3
3
  "version": "0.0.0",
4
4
  "private": true,
5
5
  "scripts": {
6
- "ui:add": "pnpm dlx shadcn@latest add"
6
+ "ui:add": "bunx shadcn@latest add"
7
7
  },
8
8
  "imports": {
9
9
  "#components/*": "./components/*.tsx",
10
10
  "#components/ui/*": "./components/ui/*.tsx",
11
+ "#components/base/*": "./components/base/*.tsx",
12
+ "#components/structure/*": "./components/structure/*.tsx",
11
13
  "#utils/*": "./utils/*.ts",
12
- "#hooks/*": "./hooks/*.ts",
13
14
  "#types/*": "./types/*.ts"
14
15
  },
15
16
  "exports": {
16
17
  "./components/*": "./components/*.tsx",
17
18
  "./components/ui/*": "./components/ui/*.tsx",
19
+ "./components/base/*": "./components/base/*.tsx",
20
+ "./components/structure/*": "./components/structure/*.tsx",
18
21
  "./utils/*": "./utils/*.ts",
22
+ "./types/*": "./types/*.ts",
19
23
  "./styles": "./styles/globals.css",
20
24
  "./icons/*": "./icons/*.tsx",
21
- "./icons/logos/*": "./icons/logos/*.tsx"
25
+ "./icons/logos/*": "./icons/logos/*.tsx",
26
+ "./icons/company-assets/*": "./icons/company-assets/*.tsx"
22
27
  },
23
28
  "dependencies": {
24
29
  "{{SCOPE}}/tailwind-config": "workspace:*",
25
- "@radix-ui/react-slot": "^1.2",
26
- "class-variance-authority": "^0.7",
27
- "clsx": "^2.1",
28
- "react": "^19",
29
- "react-dom": "^19",
30
- "shadcn": "^3",
31
- "tailwind-merge": "^3",
32
- "tw-animate-css": "^1"
30
+ "@base-ui/react": "^1.0.0",
31
+ "@phosphor-icons/react": "^2.1.10",
32
+ "@radix-ui/react-collapsible": "^1.1.12",
33
+ "@radix-ui/react-popover": "^1.1.15",
34
+ "@radix-ui/react-slot": "^1.2.4",
35
+ "class-variance-authority": "^0.7.1",
36
+ "clsx": "^2.1.1",
37
+ "react": "^19.1.0",
38
+ "react-dom": "^19.1.0",
39
+ "shadcn": "^3.6.2",
40
+ "tailwind-merge": "^3.4.0",
41
+ "tw-animate-css": "^1.4.0"
33
42
  },
34
43
  "devDependencies": {
35
44
  "{{SCOPE}}/typescript-config": "workspace:*",
@@ -1,4 +1,4 @@
1
- # Monorepo Foundation Blueprint — Turborepo + pnpm
1
+ # Monorepo Foundation Blueprint — Turborepo + bun
2
2
 
3
3
  ## Tier
4
4
 
@@ -49,8 +49,7 @@ This blueprint generates the project skeleton:
49
49
  ├── packages/ # Empty — feature blueprints add packages here
50
50
  ├── .gitignore
51
51
  ├── biome.json # Linting + formatting
52
- ├── package.json # Root workspace scripts
53
- ├── pnpm-workspace.yaml # Workspace patterns
52
+ ├── package.json # Root workspace scripts + workspaces field
54
53
  └── turbo.json # Task orchestration
55
54
  ```
56
55
 
@@ -64,9 +63,9 @@ This blueprint generates the project skeleton:
64
63
 
65
64
  ## Architecture
66
65
 
67
- ### Monorepo Tool: Turborepo + pnpm
66
+ ### Monorepo Tool: Turborepo + bun
68
67
 
69
- - **pnpm workspaces** — Fast, disk-efficient, strict dependency isolation. Hoists shared deps while preventing phantom dependencies.
68
+ - **bun workspaces** — Fast, all-in-one JavaScript runtime with built-in package management, workspace support, and near-instant installs. Workspaces are declared in the root `package.json` `workspaces` field.
70
69
  - **Turborepo** — Task orchestration with dependency-aware caching. `dev` runs all workspaces in parallel. `build` respects dependency order via `^build`.
71
70
  - **Workspace protocol** — Internal deps use `workspace:*` for automatic linking. No manual version tracking between packages.
72
71
 
@@ -195,10 +194,10 @@ apps/web/
195
194
  | Choice | Default | Alternatives |
196
195
  |--------|---------|-------------|
197
196
  | npm scope | Derived from product name | Any valid npm scope |
198
- | Package manager | pnpm | bun (documented alternative) |
197
+ | Package manager | bun | pnpm (documented alternative) |
199
198
  | Node.js version | `>=22` | Any LTS version |
200
199
 
201
- **Note on bun:** If using bun instead of pnpm, replace `pnpm-workspace.yaml` with a `workspaces` field in root `package.json`, and update the `packageManager` field. The workspace protocol (`workspace:*`) works the same way.
200
+ **Note on pnpm:** If using pnpm instead of bun, create a `pnpm-workspace.yaml` with workspace patterns, add a `"packageManager": "pnpm@9.x"` field to the root `package.json`, and remove the `workspaces` field (pnpm reads its own config file). Replace `bun install` with `pnpm install`, `bunx` with `pnpm dlx`, and `bun add -d` with `pnpm add -D`. The workspace protocol (`workspace:*`) works the same way.
202
201
 
203
202
  ---
204
203
 
@@ -206,7 +205,7 @@ apps/web/
206
205
 
207
206
  These are locked-down decisions. The blueprint doesn't offer alternatives for these:
208
207
 
209
- - **pnpm** as package manager (bun documented as alternative, but npm and yarn are not supported)
208
+ - **bun** as package manager (pnpm documented as alternative, but npm and yarn are not supported)
210
209
  - **Turborepo** for monorepo task orchestration (not Nx, Lerna, or Rush)
211
210
  - **Biome** for linting + formatting (not ESLint + Prettier)
212
211
  - **Strict TypeScript** — `strict: true` and `noUncheckedIndexedAccess: true` in every package
@@ -277,9 +276,8 @@ If no discovery was run, the foundation asks these questions directly.
277
276
 
278
277
  | Blueprint File | Target Location | Description |
279
278
  |----------------|-----------------|-------------|
280
- | `files/root/package.json` | `package.json` | Root monorepo package.json with workspace scripts |
279
+ | `files/root/package.json` | `package.json` | Root monorepo package.json with workspace scripts and workspaces field |
281
280
  | `files/root/turbo.json` | `turbo.json` | Turborepo task configuration |
282
- | `files/root/pnpm-workspace.yaml` | `pnpm-workspace.yaml` | Workspace patterns |
283
281
  | `files/root/biome.json` | `biome.json` | Biome linter + formatter config |
284
282
  | `files/root/gitignore` | `.gitignore` | Git ignore patterns |
285
283
  | `files/config/typescript-config/package.json` | `config/typescript-config/package.json` | TypeScript config package |
@@ -332,20 +330,20 @@ The lefthook config is minimal by design. Feature blueprints may add their own c
332
330
 
333
331
  | When you... | Then run... | Why |
334
332
  |---|---|---|
335
- | Add a new workspace package to `apps/`, `apis/`, `packages/`, or `config/` | Verify `pnpm-workspace.yaml` patterns cover it, then run `pnpm install` | New workspaces need to be discovered by pnpm |
336
- | Change a shared config package (`config/typescript-config/` or `config/tailwind-config/`) | Run `pnpm dev` and verify all consuming packages still build | Shared config changes cascade to all consumers |
337
- | Add a workspace dependency (e.g., `"@scope/ui": "workspace:*"`) | Run `pnpm install` then verify imports resolve | Workspace links need pnpm to wire them up |
338
- | Modify `turbo.json` task definitions | Verify `pnpm turbo run <task>` executes in the expected order | Task dependency changes affect build orchestration |
339
- | Change the TypeScript `base.json` config | Run typecheck across all workspaces: `pnpm turbo typecheck` | Base config changes affect every package |
333
+ | Add a new workspace package to `apps/`, `apis/`, `packages/`, or `config/` | Verify the `workspaces` field in root `package.json` covers it, then run `bun install` | New workspaces need to be discovered by bun |
334
+ | Change a shared config package (`config/typescript-config/` or `config/tailwind-config/`) | Run `bun dev` and verify all consuming packages still build | Shared config changes cascade to all consumers |
335
+ | Add a workspace dependency (e.g., `"@scope/ui": "workspace:*"`) | Run `bun install` then verify imports resolve | Workspace links need bun to wire them up |
336
+ | Modify `turbo.json` task definitions | Verify `bun turbo run <task>` executes in the expected order | Task dependency changes affect build orchestration |
337
+ | Change the TypeScript `base.json` config | Run typecheck across all workspaces: `bun turbo typecheck` | Base config changes affect every package |
340
338
 
341
339
  ### Condensed Rules for CLAUDE.md
342
340
  ```markdown
343
341
  ### Monorepo maintenance
344
- - After every code change: format with Biome (`pnpm biome check --write .`) before considering work complete
345
- - After adding new workspace packages: verify `pnpm-workspace.yaml` patterns match, run `pnpm install`
342
+ - After every code change: format with Biome (`bun biome check --write .`) before considering work complete
343
+ - After adding new workspace packages: verify `workspaces` field in root `package.json` includes the pattern, run `bun install`
346
344
  - After modifying shared configs (`config/typescript-config/`, `config/tailwind-config/`): verify all consumers still build
347
- - After changing `turbo.json`: verify task ordering with `pnpm turbo run <task> --dry`
348
- - After adding workspace dependencies: run `pnpm install` to create workspace links
345
+ - After changing `turbo.json`: verify task ordering with `bun turbo run <task> --dry`
346
+ - After adding workspace dependencies: run `bun install` to create workspace links
349
347
  - Keep `turbo.json` tasks with `cache: false` for any task with side effects (migrations, code generation)
350
348
  ```
351
349
 
@@ -358,7 +356,7 @@ After completion, appends to `.claude/project-context.md`:
358
356
  ```yaml
359
357
  ## Foundation
360
358
  monorepo_tool: turborepo
361
- package_manager: pnpm
359
+ package_manager: bun
362
360
  npm_scope: "{{SCOPE}}"
363
361
  node_version: ">=22"
364
362
  workspaces:
@@ -376,3 +374,4 @@ installed_at: <date>
376
374
  ```
377
375
 
378
376
 
377
+ </output>
@@ -2,6 +2,7 @@
2
2
  "name": "{{SCOPE}}",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
+ "workspaces": ["apps/*", "apis/*", "packages/*", "config/*"],
5
6
  "scripts": {
6
7
  "dev": "turbo run dev",
7
8
  "build": "turbo run build",
@@ -18,7 +19,6 @@
18
19
  "turbo": "^2",
19
20
  "typescript": "^5.9"
20
21
  },
21
- "packageManager": "pnpm@9.12.2",
22
22
  "engines": {
23
23
  "node": ">=22"
24
24
  }
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import pc4 from "picocolors";
6
6
 
7
7
  // src/constants.ts
8
8
  var API_URL = process.env["WITHMATA_API_URL"] || "https://blueprints.withmata.dev";
9
- var VERSION = "0.3.5";
9
+ var VERSION = "0.5.0";
10
10
 
11
11
  // src/lib/install-state.ts
12
12
  import { existsSync, readdirSync, lstatSync, readlinkSync } from "fs";
@@ -430,19 +430,28 @@ var SKILL_GROUPS = [
430
430
  ]
431
431
  },
432
432
  {
433
- title: "Add to Your Project",
433
+ title: "Marketing & Design",
434
434
  skills: [
435
435
  {
436
- command: "/scaffold-foundation",
437
- description: "Set up a monorepo with Turborepo and shared tooling"
436
+ command: "/copywrite",
437
+ description: "Write conversion-focused marketing page copy (pricing, about, features)"
438
438
  },
439
439
  {
440
- command: "/scaffold-db",
441
- description: "Add a database with Drizzle ORM and PostgreSQL"
440
+ command: "/copywrite-landing",
441
+ description: "Write high-converting landing page copy with CRO frameworks"
442
442
  },
443
443
  {
444
- command: "/scaffold-auth",
445
- description: "Add authentication, sessions, and organization support"
444
+ command: "/design-system",
445
+ description: "Define visual identity and generate custom Tailwind v4 tokens"
446
+ }
447
+ ]
448
+ },
449
+ {
450
+ title: "Scaffold Your Project",
451
+ skills: [
452
+ {
453
+ command: "/scaffold-foundation",
454
+ description: "Set up a monorepo with Turborepo and shared tooling"
446
455
  },
447
456
  {
448
457
  command: "/scaffold-env",
@@ -450,11 +459,19 @@ var SKILL_GROUPS = [
450
459
  },
451
460
  {
452
461
  command: "/scaffold-tailwind",
453
- description: "Add a design system with Tailwind v4 tokens and animations"
462
+ description: "Add Tailwind v4 design system (auto-detects custom design tokens)"
454
463
  },
455
464
  {
456
465
  command: "/scaffold-ui",
457
- description: "Add a component library powered by shadcn/ui"
466
+ description: "Add 31 Base UI components with Phosphor icons and form system"
467
+ },
468
+ {
469
+ command: "/scaffold-db",
470
+ description: "Add a database with Drizzle ORM and PostgreSQL"
471
+ },
472
+ {
473
+ command: "/scaffold-auth",
474
+ description: "Add authentication, sessions, and organization support"
458
475
  }
459
476
  ]
460
477
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withmata/blueprints",
3
- "version": "0.3.5",
3
+ "version": "0.5.0",
4
4
  "description": "Set up AI-powered project blueprints for Claude Code, OpenCode, and Cursor",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,20 +0,0 @@
1
- {
2
- "name": "{{SCOPE}}/tailwind-config",
3
- "version": "0.0.0",
4
- "type": "module",
5
- "private": true,
6
- "exports": {
7
- ".": "./shared-styles.css",
8
- "./postcss": "./postcss.config.mjs"
9
- },
10
- "dependencies": {
11
- "@tailwindcss/typography": "^0.5",
12
- "shadcn": "^3",
13
- "tailwind-scrollbar-hide": "^4",
14
- "tw-animate-css": "^1"
15
- },
16
- "devDependencies": {
17
- "@tailwindcss/postcss": "^4",
18
- "tailwindcss": "^4"
19
- }
20
- }
@@ -1,5 +0,0 @@
1
- packages:
2
- - "apps/*"
3
- - "apis/*"
4
- - "packages/*"
5
- - "config/*"