@archetypeai/ds-cli 0.3.17 → 0.3.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/bin.js +7 -4
- package/commands/create.js +125 -51
- package/commands/init.js +114 -36
- package/files/AGENTS.md +3 -1
- package/files/CLAUDE.md +3 -1
- package/files/rules/frontend-architecture.md +11 -0
- package/files/rules/styling.md +10 -0
- package/files/skills/create-dashboard/SKILL.md +21 -2
- package/lib/add-ds-ui-svelte.js +1 -1
- package/lib/install-fonts-local.js +212 -0
- package/lib/is-interactive.js +0 -9
- package/lib/scaffold-ds-svelte-project.js +9 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,13 +26,19 @@ Sets up a SvelteKit + Tailwind v4 + shadcn-svelte project with design tokens, co
|
|
|
26
26
|
|------|--------|---------|
|
|
27
27
|
| `--framework` | `svelte` | prompt |
|
|
28
28
|
| `--pm` | `npm`, `pnpm`, `bun`, `yarn` | prompt |
|
|
29
|
+
| `--fonts <path>` | path to PP Neue Montreal fonts folder | prompt |
|
|
30
|
+
| `--no-fonts` | skip font installation (use system fallback) | — |
|
|
29
31
|
| `--no-components` | skip component install | install all |
|
|
30
32
|
| `--codeagent` | `cursor`, `claude`, `none` | prompt |
|
|
33
|
+
| `--defaults` | force non-interactive mode | — |
|
|
31
34
|
|
|
32
35
|
```bash
|
|
33
|
-
npx @archetypeai/ds-cli create my-app --
|
|
36
|
+
npx @archetypeai/ds-cli create my-app --pm pnpm --no-fonts --codeagent claude
|
|
37
|
+
npx @archetypeai/ds-cli create my-app --pm npm --fonts /path/to/fonts --codeagent claude
|
|
34
38
|
```
|
|
35
39
|
|
|
40
|
+
**Non-interactive mode** (no TTY or `--defaults`): all required flags must be specified. The CLI lists missing options and exits so agents can ask the user before proceeding.
|
|
41
|
+
|
|
36
42
|
---
|
|
37
43
|
|
|
38
44
|
### `init` → Add DS to an existing project
|
|
@@ -47,11 +53,15 @@ Run from a SvelteKit project root. Auto-detects your package manager, installs t
|
|
|
47
53
|
| Flag | Values | Default |
|
|
48
54
|
|------|--------|---------|
|
|
49
55
|
| `--pm` | `npm`, `pnpm`, `bun`, `yarn` | auto-detect |
|
|
56
|
+
| `--fonts <path>` | path to PP Neue Montreal fonts folder | prompt |
|
|
57
|
+
| `--no-fonts` | skip font installation (use system fallback) | — |
|
|
50
58
|
| `--no-components` | skip component install | install all |
|
|
51
59
|
| `--codeagent` | `cursor`, `claude`, `none` | prompt |
|
|
60
|
+
| `--defaults` | force non-interactive mode | — |
|
|
52
61
|
|
|
53
62
|
```bash
|
|
54
|
-
npx @archetypeai/ds-cli init --pm npm --codeagent
|
|
63
|
+
npx @archetypeai/ds-cli init --pm npm --no-fonts --codeagent claude
|
|
64
|
+
npx @archetypeai/ds-cli init --pm npm --fonts /path/to/fonts --codeagent claude
|
|
55
65
|
```
|
|
56
66
|
|
|
57
67
|
---
|
package/bin.js
CHANGED
|
@@ -28,19 +28,22 @@ Usage:
|
|
|
28
28
|
Create flags:
|
|
29
29
|
--framework <svelte> Framework to use (default: prompt)
|
|
30
30
|
--pm <npm|pnpm|bun|yarn> Package manager (default: prompt)
|
|
31
|
-
--fonts
|
|
31
|
+
--fonts <path> Install fonts from local folder
|
|
32
|
+
--no-fonts Skip font installation
|
|
32
33
|
--no-components Skip component installation (default: install all)
|
|
33
34
|
--codeagent <cursor|claude|none> Agent configuration (default: prompt)
|
|
34
35
|
--defaults Skip prompts, use sensible defaults
|
|
35
36
|
|
|
36
37
|
Init flags:
|
|
37
38
|
--pm <npm|pnpm|bun|yarn> Package manager (default: auto-detect)
|
|
38
|
-
--fonts
|
|
39
|
+
--fonts <path> Install fonts from local folder
|
|
40
|
+
--no-fonts Skip font installation
|
|
39
41
|
--no-components Skip component installation (default: install all)
|
|
40
42
|
--codeagent <cursor|claude|none> Agent configuration (default: prompt)
|
|
41
|
-
--defaults
|
|
43
|
+
--defaults Force non-interactive mode
|
|
42
44
|
|
|
43
|
-
Non-interactive
|
|
45
|
+
Non-interactive mode (no TTY or --defaults):
|
|
46
|
+
All required options must be specified via flags. Missing options are listed and the CLI exits.
|
|
44
47
|
|
|
45
48
|
Add targets:
|
|
46
49
|
ds-ui-svelte Install all design system components
|
package/commands/create.js
CHANGED
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
createDemoPage,
|
|
15
15
|
installAgentConfig
|
|
16
16
|
} from '../lib/scaffold-ds-svelte-project.js';
|
|
17
|
-
import {
|
|
17
|
+
import { validateFontsPath, installLocalFonts } from '../lib/install-fonts-local.js';
|
|
18
|
+
import { isInteractive, DEFAULTS } from '../lib/is-interactive.js';
|
|
18
19
|
|
|
19
20
|
// parse flags
|
|
20
21
|
export function parseFlags(args) {
|
|
@@ -22,6 +23,7 @@ export function parseFlags(args) {
|
|
|
22
23
|
name: null,
|
|
23
24
|
framework: null,
|
|
24
25
|
pm: null,
|
|
26
|
+
fonts: null,
|
|
25
27
|
components: true,
|
|
26
28
|
agent: null,
|
|
27
29
|
defaults: false
|
|
@@ -33,6 +35,10 @@ export function parseFlags(args) {
|
|
|
33
35
|
flags.framework = args[++i];
|
|
34
36
|
} else if (arg === '--pm' && args[i + 1]) {
|
|
35
37
|
flags.pm = args[++i];
|
|
38
|
+
} else if (arg === '--fonts' && args[i + 1]) {
|
|
39
|
+
flags.fonts = args[++i];
|
|
40
|
+
} else if (arg === '--no-fonts') {
|
|
41
|
+
flags.fonts = false;
|
|
36
42
|
} else if (arg === '--no-components') {
|
|
37
43
|
flags.components = false;
|
|
38
44
|
} else if (arg === '--codeagent' && args[i + 1]) {
|
|
@@ -52,6 +58,30 @@ export async function create(args) {
|
|
|
52
58
|
const flags = parseFlags(args);
|
|
53
59
|
const interactive = isInteractive(flags);
|
|
54
60
|
|
|
61
|
+
// preflight: in non-interactive mode, list all unspecified options and exit
|
|
62
|
+
if (!interactive) {
|
|
63
|
+
const missing = [];
|
|
64
|
+
if (!flags.name)
|
|
65
|
+
missing.push(' <project-name> Project name (positional argument)');
|
|
66
|
+
if (!flags.pm) missing.push(' --pm <npm (default)|pnpm|bun|yarn> Package manager');
|
|
67
|
+
if (flags.fonts === null)
|
|
68
|
+
missing.push(' --fonts <path> | --no-fonts Internal fonts (PP Neue Montreal)');
|
|
69
|
+
if (!flags.agent) missing.push(' --codeagent <cursor|claude|none> AI agent configuration');
|
|
70
|
+
|
|
71
|
+
if (missing.length > 0) {
|
|
72
|
+
console.log(
|
|
73
|
+
'[CONFIGURATION REQUIRED] Do not assume defaults. Ask the user to choose each option:\n\n' +
|
|
74
|
+
missing.join('\n') +
|
|
75
|
+
'\n\nOptional:\n' +
|
|
76
|
+
' --no-components Skip component installation\n\n' +
|
|
77
|
+
'Once the user has answered, re-run with their choices:\n' +
|
|
78
|
+
' ds create my-app --pm <choice> --fonts <path> --codeagent <choice>\n' +
|
|
79
|
+
' ds create my-app --pm <choice> --no-fonts --codeagent <choice>\n'
|
|
80
|
+
);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
55
85
|
p.intro('Create a new project using Archetype AI Design System.');
|
|
56
86
|
|
|
57
87
|
// specify project name
|
|
@@ -95,44 +125,87 @@ export async function create(args) {
|
|
|
95
125
|
process.exit(1);
|
|
96
126
|
}
|
|
97
127
|
|
|
98
|
-
// specify framework
|
|
99
|
-
let framework = flags.framework;
|
|
100
|
-
if (!framework) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (p.isCancel(framework)) {
|
|
109
|
-
p.cancel('Setup cancelled.');
|
|
110
|
-
process.exit(0);
|
|
111
|
-
}
|
|
128
|
+
// specify framework (only svelte supported, default silently)
|
|
129
|
+
let framework = flags.framework || 'svelte';
|
|
130
|
+
if (!flags.framework && interactive) {
|
|
131
|
+
framework = await p.select({
|
|
132
|
+
message: 'Which framework?',
|
|
133
|
+
options: [{ value: 'svelte', label: 'SvelteKit', hint: 'Svelte 5 + Tailwind v4, default' }]
|
|
134
|
+
});
|
|
135
|
+
if (p.isCancel(framework)) {
|
|
136
|
+
p.cancel('Setup cancelled.');
|
|
137
|
+
process.exit(0);
|
|
112
138
|
}
|
|
113
139
|
}
|
|
114
140
|
|
|
115
141
|
// specify package manager
|
|
116
142
|
let pmName = flags.pm;
|
|
117
143
|
if (!pmName) {
|
|
118
|
-
|
|
119
|
-
|
|
144
|
+
pmName = await p.select({
|
|
145
|
+
message: 'Which package manager?',
|
|
146
|
+
options: pmNames.map((n) => ({
|
|
147
|
+
value: n,
|
|
148
|
+
label: n,
|
|
149
|
+
...(n === DEFAULTS.pm && { hint: 'default' })
|
|
150
|
+
}))
|
|
151
|
+
});
|
|
152
|
+
if (p.isCancel(pmName)) {
|
|
153
|
+
p.cancel('Setup cancelled.');
|
|
154
|
+
process.exit(0);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const pm = getPm(pmName);
|
|
158
|
+
|
|
159
|
+
// specify fonts
|
|
160
|
+
let fontsPath = null;
|
|
161
|
+
let includeFonts = false;
|
|
162
|
+
if (flags.fonts === false) {
|
|
163
|
+
// --no-fonts: skip
|
|
164
|
+
} else if (typeof flags.fonts === 'string') {
|
|
165
|
+
fontsPath = flags.fonts;
|
|
166
|
+
const result = validateFontsPath(fontsPath);
|
|
167
|
+
if (!result.valid) {
|
|
168
|
+
if (!interactive) {
|
|
169
|
+
p.log.error(result.error);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
p.log.warn(result.error);
|
|
173
|
+
p.log.warn('Continuing without fonts.');
|
|
174
|
+
fontsPath = null;
|
|
120
175
|
} else {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
176
|
+
includeFonts = true;
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
const useFonts = await p.confirm({
|
|
180
|
+
message: 'Do you want to use internal fonts?',
|
|
181
|
+
initialValue: false
|
|
182
|
+
});
|
|
183
|
+
if (p.isCancel(useFonts)) {
|
|
184
|
+
p.cancel('Setup cancelled.');
|
|
185
|
+
process.exit(0);
|
|
186
|
+
}
|
|
187
|
+
if (useFonts) {
|
|
188
|
+
const fontInput = await p.text({
|
|
189
|
+
message: 'Drop your fonts folder here:',
|
|
190
|
+
placeholder: '/path/to/fonts'
|
|
128
191
|
});
|
|
129
|
-
if (p.isCancel(
|
|
192
|
+
if (p.isCancel(fontInput)) {
|
|
130
193
|
p.cancel('Setup cancelled.');
|
|
131
194
|
process.exit(0);
|
|
132
195
|
}
|
|
196
|
+
if (fontInput && fontInput.trim()) {
|
|
197
|
+
fontsPath = fontInput.trim();
|
|
198
|
+
const result = validateFontsPath(fontsPath);
|
|
199
|
+
if (!result.valid) {
|
|
200
|
+
p.log.warn(result.error);
|
|
201
|
+
p.log.warn('Continuing without fonts.');
|
|
202
|
+
fontsPath = null;
|
|
203
|
+
} else {
|
|
204
|
+
includeFonts = true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
133
207
|
}
|
|
134
208
|
}
|
|
135
|
-
const pm = getPm(pmName);
|
|
136
209
|
|
|
137
210
|
// verify package manager is installed
|
|
138
211
|
if (!isPmInstalled(pmName)) {
|
|
@@ -177,8 +250,22 @@ export async function create(args) {
|
|
|
177
250
|
// init shadcn-svelte
|
|
178
251
|
await initShadcn(pm, projectPath);
|
|
179
252
|
|
|
253
|
+
// install local fonts
|
|
254
|
+
if (includeFonts && fontsPath) {
|
|
255
|
+
const s = p.spinner();
|
|
256
|
+
s.start('Installing fonts');
|
|
257
|
+
const fontResult = installLocalFonts(fontsPath, projectPath);
|
|
258
|
+
if (fontResult.success) {
|
|
259
|
+
s.stop(`${fontResult.fileCount} font files installed`);
|
|
260
|
+
} else {
|
|
261
|
+
s.stop('Failed to install fonts');
|
|
262
|
+
p.log.warn(fontResult.error);
|
|
263
|
+
p.log.warn('Continuing without fonts.');
|
|
264
|
+
includeFonts = false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
180
268
|
// configure CSS
|
|
181
|
-
const includeFonts = false;
|
|
182
269
|
configureCss(projectPath, includeFonts);
|
|
183
270
|
|
|
184
271
|
// set up linting and formatting
|
|
@@ -202,33 +289,20 @@ export async function create(args) {
|
|
|
202
289
|
// specify agent config
|
|
203
290
|
let agent = flags.agent;
|
|
204
291
|
if (!agent) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (p.isCancel(agent)) {
|
|
217
|
-
p.cancel('Setup cancelled.');
|
|
218
|
-
process.exit(0);
|
|
219
|
-
}
|
|
292
|
+
agent = await p.select({
|
|
293
|
+
message: 'Install AI agent configuration?',
|
|
294
|
+
options: [
|
|
295
|
+
{ value: 'none', label: 'None' },
|
|
296
|
+
{ value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
|
|
297
|
+
{ value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules, default' }
|
|
298
|
+
]
|
|
299
|
+
});
|
|
300
|
+
if (p.isCancel(agent)) {
|
|
301
|
+
p.cancel('Setup cancelled.');
|
|
302
|
+
process.exit(0);
|
|
220
303
|
}
|
|
221
304
|
}
|
|
222
305
|
|
|
223
|
-
// log defaults notice
|
|
224
|
-
if (!interactive) {
|
|
225
|
-
const applied = {};
|
|
226
|
-
if (!flags.framework) applied.framework = framework;
|
|
227
|
-
if (!flags.pm) applied.pm = pmName;
|
|
228
|
-
if (!flags.agent) applied.codeagent = agent;
|
|
229
|
-
logDefaultsNotice(applied);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
306
|
const validAgents = ['cursor', 'claude', 'none'];
|
|
233
307
|
if (!validAgents.includes(agent)) {
|
|
234
308
|
p.log.error(`Invalid --codeagent value "${agent}". Must be one of: ${validAgents.join(', ')}`);
|
package/commands/init.js
CHANGED
|
@@ -13,12 +13,14 @@ import {
|
|
|
13
13
|
installComponents,
|
|
14
14
|
installAgentConfig
|
|
15
15
|
} from '../lib/scaffold-ds-svelte-project.js';
|
|
16
|
-
import {
|
|
16
|
+
import { validateFontsPath, installLocalFonts } from '../lib/install-fonts-local.js';
|
|
17
|
+
import { isInteractive, DEFAULTS } from '../lib/is-interactive.js';
|
|
17
18
|
|
|
18
19
|
// parse flags
|
|
19
20
|
export function parseFlags(args) {
|
|
20
21
|
const flags = {
|
|
21
22
|
pm: null,
|
|
23
|
+
fonts: null,
|
|
22
24
|
components: true,
|
|
23
25
|
agent: null,
|
|
24
26
|
defaults: false
|
|
@@ -28,6 +30,10 @@ export function parseFlags(args) {
|
|
|
28
30
|
const arg = args[i];
|
|
29
31
|
if (arg === '--pm' && args[i + 1]) {
|
|
30
32
|
flags.pm = args[++i];
|
|
33
|
+
} else if (arg === '--fonts' && args[i + 1]) {
|
|
34
|
+
flags.fonts = args[++i];
|
|
35
|
+
} else if (arg === '--no-fonts') {
|
|
36
|
+
flags.fonts = false;
|
|
31
37
|
} else if (arg === '--no-components') {
|
|
32
38
|
flags.components = false;
|
|
33
39
|
} else if (arg === '--codeagent' && args[i + 1]) {
|
|
@@ -57,6 +63,29 @@ export async function init(args) {
|
|
|
57
63
|
const interactive = isInteractive(flags);
|
|
58
64
|
const projectPath = process.cwd();
|
|
59
65
|
|
|
66
|
+
// preflight: in non-interactive mode, list all unspecified options and exit
|
|
67
|
+
if (!interactive) {
|
|
68
|
+
const missing = [];
|
|
69
|
+
if (!flags.pm && !detectPm(projectPath))
|
|
70
|
+
missing.push(' --pm <npm (default)|pnpm|bun|yarn> Package manager');
|
|
71
|
+
if (flags.fonts === null)
|
|
72
|
+
missing.push(' --fonts <path> | --no-fonts Internal fonts (PP Neue Montreal)');
|
|
73
|
+
if (!flags.agent) missing.push(' --codeagent <cursor|claude|none> AI agent configuration');
|
|
74
|
+
|
|
75
|
+
if (missing.length > 0) {
|
|
76
|
+
console.log(
|
|
77
|
+
'[CONFIGURATION REQUIRED] Do not assume defaults. Ask the user to choose each option:\n\n' +
|
|
78
|
+
missing.join('\n') +
|
|
79
|
+
'\n\nOptional:\n' +
|
|
80
|
+
' --no-components Skip component installation\n\n' +
|
|
81
|
+
'Once the user has answered, re-run with their choices:\n' +
|
|
82
|
+
' ds init --pm <choice> --fonts <path> --codeagent <choice>\n' +
|
|
83
|
+
' ds init --pm <choice> --no-fonts --codeagent <choice>\n'
|
|
84
|
+
);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
60
89
|
// validate --pm flag
|
|
61
90
|
if (flags.pm && !pmNames.includes(flags.pm)) {
|
|
62
91
|
p.log.error(`Invalid --pm value "${flags.pm}". Must be one of: ${pmNames.join(', ')}`);
|
|
@@ -91,32 +120,71 @@ export async function init(args) {
|
|
|
91
120
|
}
|
|
92
121
|
}
|
|
93
122
|
if (!pmName) {
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
pmName = await p.select({
|
|
124
|
+
message: 'Which package manager?',
|
|
125
|
+
options: pmNames.map((n) => ({
|
|
126
|
+
value: n,
|
|
127
|
+
label: n,
|
|
128
|
+
...(n === DEFAULTS.pm && { hint: 'default' })
|
|
129
|
+
}))
|
|
130
|
+
});
|
|
131
|
+
if (p.isCancel(pmName)) {
|
|
132
|
+
p.cancel('Setup cancelled.');
|
|
133
|
+
process.exit(0);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const pm = getPm(pmName);
|
|
137
|
+
|
|
138
|
+
// specify fonts
|
|
139
|
+
let fontsPath = null;
|
|
140
|
+
let includeFonts = false;
|
|
141
|
+
if (flags.fonts === false) {
|
|
142
|
+
// --no-fonts: skip
|
|
143
|
+
} else if (typeof flags.fonts === 'string') {
|
|
144
|
+
fontsPath = flags.fonts;
|
|
145
|
+
const result = validateFontsPath(fontsPath);
|
|
146
|
+
if (!result.valid) {
|
|
147
|
+
if (!interactive) {
|
|
148
|
+
p.log.error(result.error);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
p.log.warn(result.error);
|
|
152
|
+
p.log.warn('Continuing without fonts.');
|
|
153
|
+
fontsPath = null;
|
|
96
154
|
} else {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
155
|
+
includeFonts = true;
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
const useFonts = await p.confirm({
|
|
159
|
+
message: 'Do you want to use internal fonts?',
|
|
160
|
+
initialValue: false
|
|
161
|
+
});
|
|
162
|
+
if (p.isCancel(useFonts)) {
|
|
163
|
+
p.cancel('Setup cancelled.');
|
|
164
|
+
process.exit(0);
|
|
165
|
+
}
|
|
166
|
+
if (useFonts) {
|
|
167
|
+
const fontInput = await p.text({
|
|
168
|
+
message: 'Drop your fonts folder here:',
|
|
169
|
+
placeholder: '/path/to/fonts'
|
|
104
170
|
});
|
|
105
|
-
if (p.isCancel(
|
|
171
|
+
if (p.isCancel(fontInput)) {
|
|
106
172
|
p.cancel('Setup cancelled.');
|
|
107
173
|
process.exit(0);
|
|
108
174
|
}
|
|
175
|
+
if (fontInput && fontInput.trim()) {
|
|
176
|
+
fontsPath = fontInput.trim();
|
|
177
|
+
const result = validateFontsPath(fontsPath);
|
|
178
|
+
if (!result.valid) {
|
|
179
|
+
p.log.warn(result.error);
|
|
180
|
+
p.log.warn('Continuing without fonts.');
|
|
181
|
+
fontsPath = null;
|
|
182
|
+
} else {
|
|
183
|
+
includeFonts = true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
109
186
|
}
|
|
110
187
|
}
|
|
111
|
-
const pm = getPm(pmName);
|
|
112
|
-
|
|
113
|
-
// log defaults notice
|
|
114
|
-
if (!interactive) {
|
|
115
|
-
const applied = {};
|
|
116
|
-
if (!flags.pm) applied.pm = pmName;
|
|
117
|
-
if (!flags.agent) applied.codeagent = DEFAULTS.agent;
|
|
118
|
-
logDefaultsNotice(applied);
|
|
119
|
-
}
|
|
120
188
|
|
|
121
189
|
// verify package manager is installed
|
|
122
190
|
if (!isPmInstalled(pmName)) {
|
|
@@ -142,8 +210,22 @@ export async function init(args) {
|
|
|
142
210
|
// init shadcn-svelte
|
|
143
211
|
await initShadcn(pm, projectPath);
|
|
144
212
|
|
|
213
|
+
// install local fonts
|
|
214
|
+
if (includeFonts && fontsPath) {
|
|
215
|
+
const s = p.spinner();
|
|
216
|
+
s.start('Installing fonts');
|
|
217
|
+
const fontResult = installLocalFonts(fontsPath, projectPath);
|
|
218
|
+
if (fontResult.success) {
|
|
219
|
+
s.stop(`${fontResult.fileCount} font files installed`);
|
|
220
|
+
} else {
|
|
221
|
+
s.stop('Failed to install fonts');
|
|
222
|
+
p.log.warn(fontResult.error);
|
|
223
|
+
p.log.warn('Continuing without fonts.');
|
|
224
|
+
includeFonts = false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
145
228
|
// configure CSS (prepend to existing)
|
|
146
|
-
const includeFonts = false;
|
|
147
229
|
prependCss(projectPath, includeFonts);
|
|
148
230
|
|
|
149
231
|
// set up linting and formatting
|
|
@@ -167,21 +249,17 @@ export async function init(args) {
|
|
|
167
249
|
// specify agent config
|
|
168
250
|
let agent = flags.agent;
|
|
169
251
|
if (!agent) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (p.isCancel(agent)) {
|
|
182
|
-
p.cancel('Setup cancelled.');
|
|
183
|
-
process.exit(0);
|
|
184
|
-
}
|
|
252
|
+
agent = await p.select({
|
|
253
|
+
message: 'Install AI agent configuration?',
|
|
254
|
+
options: [
|
|
255
|
+
{ value: 'none', label: 'None' },
|
|
256
|
+
{ value: 'cursor', label: 'Cursor', hint: 'AGENTS.md + skills + rules' },
|
|
257
|
+
{ value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md + skills + rules, default' }
|
|
258
|
+
]
|
|
259
|
+
});
|
|
260
|
+
if (p.isCancel(agent)) {
|
|
261
|
+
p.cancel('Setup cancelled.');
|
|
262
|
+
process.exit(0);
|
|
185
263
|
}
|
|
186
264
|
}
|
|
187
265
|
|
package/files/AGENTS.md
CHANGED
|
@@ -49,7 +49,9 @@ Standard Tailwind is fine for:
|
|
|
49
49
|
Before building a new component, fetch the pattern catalog from:
|
|
50
50
|
`https://design-system.archetypeai.workers.dev/r/patterns.json`
|
|
51
51
|
|
|
52
|
-
Each entry includes a `name`, `title`, `description`, and `registryDependencies`. Reuse or extend existing patterns instead of rebuilding from scratch.
|
|
52
|
+
Each entry includes a `name`, `title`, `description`, and `registryDependencies`. Reuse or extend existing patterns instead of rebuilding from scratch.
|
|
53
|
+
|
|
54
|
+
Before installing, check if the pattern already exists locally in `$lib/components/ui/patterns/{name}/`. Only install if it is missing:
|
|
53
55
|
`npx shadcn-svelte@latest add https://design-system.archetypeai.workers.dev/r/{name}.json`
|
|
54
56
|
|
|
55
57
|
## Skills
|
package/files/CLAUDE.md
CHANGED
|
@@ -49,7 +49,9 @@ Standard Tailwind is fine for:
|
|
|
49
49
|
Before building a new component, fetch the pattern catalog from:
|
|
50
50
|
`https://design-system.archetypeai.workers.dev/r/patterns.json`
|
|
51
51
|
|
|
52
|
-
Each entry includes a `name`, `title`, `description`, and `registryDependencies`. Reuse or extend existing patterns instead of rebuilding from scratch.
|
|
52
|
+
Each entry includes a `name`, `title`, `description`, and `registryDependencies`. Reuse or extend existing patterns instead of rebuilding from scratch.
|
|
53
|
+
|
|
54
|
+
Before installing, check if the pattern already exists locally in `$lib/components/ui/patterns/{name}/`. Only install if it is missing:
|
|
53
55
|
`npx shadcn-svelte@latest add https://design-system.archetypeai.workers.dev/r/{name}.json`
|
|
54
56
|
|
|
55
57
|
## Skills
|
|
@@ -31,6 +31,17 @@ The project includes pattern components that demonstrate these conventions. Stud
|
|
|
31
31
|
|
|
32
32
|
Check if an existing pattern fits before building a new one. Use `@skills/build-pattern` to create new patterns that follow these same conventions.
|
|
33
33
|
|
|
34
|
+
## Directory structure
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
$lib/components/ui/
|
|
38
|
+
primitives/ — DS registry primitives (Card, Badge, Button, etc.)
|
|
39
|
+
patterns/ — DS registry patterns (BackgroundCard, FlatLogItem, etc.)
|
|
40
|
+
custom/ — Project-specific components not from the registry
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Place custom components (ones you create for this project that are not installed from the registry) in `$lib/components/ui/custom/`. Never put custom components directly in `ui/` next to `primitives/` and `patterns/`.
|
|
44
|
+
|
|
34
45
|
## Component conventions
|
|
35
46
|
|
|
36
47
|
Follow `@rules/components` for the full conventions. The essentials:
|
package/files/rules/styling.md
CHANGED
|
@@ -90,6 +90,16 @@ In your global CSS file:
|
|
|
90
90
|
|
|
91
91
|
Order matters - tokens must come before Tailwind.
|
|
92
92
|
|
|
93
|
+
### Hide Scrollbars
|
|
94
|
+
|
|
95
|
+
Always add this rule to the root layout CSS (`src/app.css` or `src/routes/layout.css`) to hide visible scrollbars in ScrollArea components:
|
|
96
|
+
|
|
97
|
+
```css
|
|
98
|
+
[data-slot='scroll-area-scrollbar'] {
|
|
99
|
+
display: none !important;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
93
103
|
## Tailwind v4 Specifics
|
|
94
104
|
|
|
95
105
|
### @theme Directive
|
|
@@ -33,7 +33,7 @@ Dashboards fill the entire viewport with no scrolling:
|
|
|
33
33
|
Unless the user explicitly asks for a different layout:
|
|
34
34
|
|
|
35
35
|
- **Equal-width columns** — use `grid-cols-2`, `grid-cols-3`, etc. Never mix fixed and fluid widths for card grids (e.g., don't use `grid-cols-[300px_1fr]` for cards — that's for sidebar layouts only)
|
|
36
|
-
- **
|
|
36
|
+
- **Cards fill available height** — cards must stretch to fill their grid cell or flex container. Add `max-h-full` to constrain content. For asymmetric layouts (stacked cards in one column, full-height card in another), use a flex column with `flex-1` on the card that should grow
|
|
37
37
|
- **Consistent spacing** — always use `gap-4` between cards and `p-4` padding around the grid
|
|
38
38
|
|
|
39
39
|
## Menubar
|
|
@@ -123,7 +123,7 @@ For co-branding, pass a `partnerLogo` snippet to replace the default placeholder
|
|
|
123
123
|
</main>
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
### Grid of Cards
|
|
126
|
+
### Grid of Cards (Equal)
|
|
127
127
|
|
|
128
128
|
```svelte
|
|
129
129
|
<main class="grid grid-cols-2 grid-rows-2 gap-4 overflow-hidden p-4">
|
|
@@ -134,6 +134,25 @@ For co-branding, pass a `partnerLogo` snippet to replace the default placeholder
|
|
|
134
134
|
</main>
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
+
### Asymmetric Cards (Stacked Left + Full-Height Right)
|
|
138
|
+
|
|
139
|
+
When one column has multiple cards and the other has a single tall card, use `grid-rows-subgrid` or nested flex columns. Cards must stretch to fill available height — never leave empty space at the bottom.
|
|
140
|
+
|
|
141
|
+
```svelte
|
|
142
|
+
<main class="grid grid-cols-[1fr_2fr] gap-4 overflow-hidden p-4">
|
|
143
|
+
<!-- Left column: stacked cards that fill height -->
|
|
144
|
+
<div class="flex flex-col gap-4 overflow-hidden">
|
|
145
|
+
<Card class="max-h-full"><!-- input --></Card>
|
|
146
|
+
<Card class="max-h-full"><!-- status --></Card>
|
|
147
|
+
<Card class="max-h-full flex-1"><!-- summary (grows to fill remaining space) --></Card>
|
|
148
|
+
</div>
|
|
149
|
+
<!-- Right column: single card spanning full height -->
|
|
150
|
+
<Card class="max-h-full overflow-hidden"><!-- log / results --></Card>
|
|
151
|
+
</main>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The `flex-1` on the last left-column card makes it grow to fill remaining vertical space. Adjust column ratio (`1fr_2fr`, `1fr_1fr`, etc.) to match content needs.
|
|
155
|
+
|
|
137
156
|
## Key Tailwind Classes
|
|
138
157
|
|
|
139
158
|
| Class | Purpose |
|
package/lib/add-ds-ui-svelte.js
CHANGED
|
@@ -59,7 +59,7 @@ export async function addDsUiSvelte() {
|
|
|
59
59
|
await execFileAsync(
|
|
60
60
|
dlxCmd,
|
|
61
61
|
[...dlxArgs, 'shadcn-svelte@latest', 'add', ...componentUrls, '--yes', '--overwrite'],
|
|
62
|
-
{ stdio: 'pipe', cwd: projectDir }
|
|
62
|
+
{ stdio: 'pipe', maxBuffer: 10 * 1024 * 1024, cwd: projectDir }
|
|
63
63
|
);
|
|
64
64
|
|
|
65
65
|
installSpinner.stop('All components installed');
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { existsSync, readdirSync, copyFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
|
|
4
|
+
// all 15 required font files
|
|
5
|
+
export const REQUIRED_FONTS = [
|
|
6
|
+
// PP Neue Montreal Sans (.ttf)
|
|
7
|
+
'PPNeueMontreal-Thin.ttf',
|
|
8
|
+
'PPNeueMontreal-ThinItalic.ttf',
|
|
9
|
+
'PPNeueMontreal-Light.ttf',
|
|
10
|
+
'PPNeueMontreal-Regular.ttf',
|
|
11
|
+
'PPNeueMontreal-Italic.ttf',
|
|
12
|
+
'PPNeueMontreal-Book.ttf',
|
|
13
|
+
'PPNeueMontreal-Medium.ttf',
|
|
14
|
+
'PPNeueMontreal-Bold.ttf',
|
|
15
|
+
'PPNeueMontreal-BoldItalic.ttf',
|
|
16
|
+
// PP Neue Montreal Mono (.otf)
|
|
17
|
+
'PPNeueMontrealMono-Thin.otf',
|
|
18
|
+
'PPNeueMontrealMono-Regular.otf',
|
|
19
|
+
'PPNeueMontrealMono-RegularItalic.otf',
|
|
20
|
+
'PPNeueMontrealMono-Book.otf',
|
|
21
|
+
'PPNeueMontrealMono-Medium.otf',
|
|
22
|
+
'PPNeueMontrealMono-Bold.otf'
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// hardcoded fonts.css template
|
|
26
|
+
export const FONTS_CSS = `/* PP Neue Montreal Sans*/
|
|
27
|
+
|
|
28
|
+
@font-face {
|
|
29
|
+
font-family: 'PP Neue Montreal';
|
|
30
|
+
src: url('/fonts/PPNeueMontreal-Thin.ttf') format('truetype');
|
|
31
|
+
font-weight: 100;
|
|
32
|
+
font-style: normal;
|
|
33
|
+
font-display: swap;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@font-face {
|
|
37
|
+
font-family: 'PP Neue Montreal';
|
|
38
|
+
src: url('/fonts/PPNeueMontreal-ThinItalic.ttf') format('truetype');
|
|
39
|
+
font-weight: 100;
|
|
40
|
+
font-style: italic;
|
|
41
|
+
font-display: swap;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@font-face {
|
|
45
|
+
font-family: 'PP Neue Montreal';
|
|
46
|
+
src: url('/fonts/PPNeueMontreal-Light.ttf') format('truetype');
|
|
47
|
+
font-weight: 300;
|
|
48
|
+
font-style: normal;
|
|
49
|
+
font-display: swap;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@font-face {
|
|
53
|
+
font-family: 'PP Neue Montreal';
|
|
54
|
+
src: url('/fonts/PPNeueMontreal-Regular.ttf') format('truetype');
|
|
55
|
+
font-weight: 400;
|
|
56
|
+
font-style: normal;
|
|
57
|
+
font-display: swap;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@font-face {
|
|
61
|
+
font-family: 'PP Neue Montreal';
|
|
62
|
+
src: url('/fonts/PPNeueMontreal-Italic.ttf') format('truetype');
|
|
63
|
+
font-weight: 400;
|
|
64
|
+
font-style: italic;
|
|
65
|
+
font-display: swap;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@font-face {
|
|
69
|
+
font-family: 'PP Neue Montreal';
|
|
70
|
+
src: url('/fonts/PPNeueMontreal-Book.ttf') format('truetype');
|
|
71
|
+
font-weight: 400;
|
|
72
|
+
font-style: normal;
|
|
73
|
+
font-display: swap;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@font-face {
|
|
77
|
+
font-family: 'PP Neue Montreal';
|
|
78
|
+
src: url('/fonts/PPNeueMontreal-Medium.ttf') format('truetype');
|
|
79
|
+
font-weight: 500;
|
|
80
|
+
font-style: normal;
|
|
81
|
+
font-display: swap;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@font-face {
|
|
85
|
+
font-family: 'PP Neue Montreal';
|
|
86
|
+
src: url('/fonts/PPNeueMontreal-Bold.ttf') format('truetype');
|
|
87
|
+
font-weight: 700;
|
|
88
|
+
font-style: normal;
|
|
89
|
+
font-display: swap;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@font-face {
|
|
93
|
+
font-family: 'PP Neue Montreal';
|
|
94
|
+
src: url('/fonts/PPNeueMontreal-BoldItalic.ttf') format('truetype');
|
|
95
|
+
font-weight: 700;
|
|
96
|
+
font-style: italic;
|
|
97
|
+
font-display: swap;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* PP Neue Montreal Mono */
|
|
101
|
+
|
|
102
|
+
@font-face {
|
|
103
|
+
font-family: 'PP Neue Montreal Mono';
|
|
104
|
+
src: url('/fonts/PPNeueMontrealMono-Thin.otf') format('opentype');
|
|
105
|
+
font-weight: 100;
|
|
106
|
+
font-style: normal;
|
|
107
|
+
font-display: swap;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@font-face {
|
|
111
|
+
font-family: 'PP Neue Montreal Mono';
|
|
112
|
+
src: url('/fonts/PPNeueMontrealMono-Regular.otf') format('opentype');
|
|
113
|
+
font-weight: 400;
|
|
114
|
+
font-style: normal;
|
|
115
|
+
font-display: swap;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@font-face {
|
|
119
|
+
font-family: 'PP Neue Montreal Mono';
|
|
120
|
+
src: url('/fonts/PPNeueMontrealMono-RegularItalic.otf') format('opentype');
|
|
121
|
+
font-weight: 400;
|
|
122
|
+
font-style: italic;
|
|
123
|
+
font-display: swap;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@font-face {
|
|
127
|
+
font-family: 'PP Neue Montreal Mono';
|
|
128
|
+
src: url('/fonts/PPNeueMontrealMono-Book.otf') format('opentype');
|
|
129
|
+
font-weight: 400;
|
|
130
|
+
font-style: normal;
|
|
131
|
+
font-display: swap;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@font-face {
|
|
135
|
+
font-family: 'PP Neue Montreal Mono';
|
|
136
|
+
src: url('/fonts/PPNeueMontrealMono-Medium.otf') format('opentype');
|
|
137
|
+
font-weight: 500;
|
|
138
|
+
font-style: normal;
|
|
139
|
+
font-display: swap;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@font-face {
|
|
143
|
+
font-family: 'PP Neue Montreal Mono';
|
|
144
|
+
src: url('/fonts/PPNeueMontrealMono-Bold.otf') format('opentype');
|
|
145
|
+
font-weight: 700;
|
|
146
|
+
font-style: normal;
|
|
147
|
+
font-display: swap;
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
|
|
151
|
+
// validate that a directory contains all required font files
|
|
152
|
+
export function validateFontsPath(fontsPath) {
|
|
153
|
+
const resolved = resolve(fontsPath);
|
|
154
|
+
|
|
155
|
+
if (!existsSync(resolved)) {
|
|
156
|
+
return { valid: false, missing: REQUIRED_FONTS, error: `Path does not exist: ${resolved}` };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let entries;
|
|
160
|
+
try {
|
|
161
|
+
entries = readdirSync(resolved);
|
|
162
|
+
} catch {
|
|
163
|
+
return { valid: false, missing: REQUIRED_FONTS, error: `Cannot read directory: ${resolved}` };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const missing = REQUIRED_FONTS.filter((f) => !entries.includes(f));
|
|
167
|
+
if (missing.length > 0) {
|
|
168
|
+
return {
|
|
169
|
+
valid: false,
|
|
170
|
+
missing,
|
|
171
|
+
error: `Missing ${missing.length} font file(s): ${missing.join(', ')}`
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { valid: true, missing: [] };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// copy required font files to <project>/static/fonts/
|
|
179
|
+
export function copyFontsToStatic(fontsPath, projectPath) {
|
|
180
|
+
const src = resolve(fontsPath);
|
|
181
|
+
const dest = join(projectPath, 'static', 'fonts');
|
|
182
|
+
mkdirSync(dest, { recursive: true });
|
|
183
|
+
|
|
184
|
+
for (const file of REQUIRED_FONTS) {
|
|
185
|
+
copyFileSync(join(src, file), join(dest, file));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return REQUIRED_FONTS.length;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// write fonts.css to src/routes/fonts.css
|
|
192
|
+
function writeFontsCss(projectPath) {
|
|
193
|
+
const cssPath = join(projectPath, 'src', 'routes', 'fonts.css');
|
|
194
|
+
const dir = join(projectPath, 'src', 'routes');
|
|
195
|
+
if (!existsSync(dir)) {
|
|
196
|
+
mkdirSync(dir, { recursive: true });
|
|
197
|
+
}
|
|
198
|
+
writeFileSync(cssPath, FONTS_CSS);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// orchestrate: validate, copy fonts, write fonts.css
|
|
202
|
+
export function installLocalFonts(fontsPath, projectPath) {
|
|
203
|
+
const validation = validateFontsPath(fontsPath);
|
|
204
|
+
if (!validation.valid) {
|
|
205
|
+
return { success: false, fileCount: 0, error: validation.error };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const fileCount = copyFontsToStatic(fontsPath, projectPath);
|
|
209
|
+
writeFontsCss(projectPath);
|
|
210
|
+
|
|
211
|
+
return { success: true, fileCount };
|
|
212
|
+
}
|
package/lib/is-interactive.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as p from '@clack/prompts';
|
|
2
|
-
|
|
3
1
|
export const DEFAULTS = {
|
|
4
2
|
framework: 'svelte',
|
|
5
3
|
pm: 'npm',
|
|
@@ -10,10 +8,3 @@ export function isInteractive(flags) {
|
|
|
10
8
|
if (flags.defaults) return false;
|
|
11
9
|
return !!process.stdin.isTTY;
|
|
12
10
|
}
|
|
13
|
-
|
|
14
|
-
export function logDefaultsNotice(applied) {
|
|
15
|
-
const parts = Object.entries(applied).map(([k, v]) => `${k}=${v}`);
|
|
16
|
-
if (parts.length > 0) {
|
|
17
|
-
p.log.info(`Non-interactive mode: using defaults (${parts.join(', ')})`);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -9,7 +9,7 @@ const execFileAsync = promisify(execFile);
|
|
|
9
9
|
|
|
10
10
|
// run a command without a shell to prevent injection
|
|
11
11
|
async function run(command, args, opts) {
|
|
12
|
-
await execFileAsync(command, args, { stdio: 'pipe', ...opts });
|
|
12
|
+
await execFileAsync(command, args, { stdio: 'pipe', maxBuffer: 10 * 1024 * 1024, ...opts });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
// write a file
|
|
@@ -88,23 +88,6 @@ export async function installTokens(pm, projectPath) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// install internal fonts package
|
|
92
|
-
export async function installFonts(pm, projectPath) {
|
|
93
|
-
const [cmd, ...baseArgs] = splitCmd(pm.install);
|
|
94
|
-
const args = [...baseArgs, '@archetypeai/ds-lib-fonts-internal'];
|
|
95
|
-
const s = p.spinner();
|
|
96
|
-
s.start('Installing internal fonts');
|
|
97
|
-
try {
|
|
98
|
-
await run(cmd, args, { cwd: projectPath });
|
|
99
|
-
s.stop('Internal fonts installed');
|
|
100
|
-
return true;
|
|
101
|
-
} catch {
|
|
102
|
-
s.stop('Failed to install internal fonts');
|
|
103
|
-
p.log.warn('Make sure you are authenticated with npm (run: npm login)');
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
91
|
// init shadcn-svelte
|
|
109
92
|
export async function initShadcn(pm, projectPath) {
|
|
110
93
|
const s = p.spinner();
|
|
@@ -112,19 +95,16 @@ export async function initShadcn(pm, projectPath) {
|
|
|
112
95
|
try {
|
|
113
96
|
const componentsJson = {
|
|
114
97
|
$schema: 'https://shadcn-svelte.com/schema.json',
|
|
115
|
-
style: 'default',
|
|
116
98
|
tailwind: {
|
|
117
|
-
config: '',
|
|
118
99
|
css: 'src/routes/layout.css',
|
|
119
|
-
baseColor: 'slate'
|
|
120
|
-
cssVariables: true,
|
|
121
|
-
prefix: ''
|
|
100
|
+
baseColor: 'slate'
|
|
122
101
|
},
|
|
123
102
|
aliases: {
|
|
124
103
|
utils: '$lib/utils',
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
104
|
+
ui: '$lib/components/ui',
|
|
105
|
+
components: '$lib/components',
|
|
106
|
+
hooks: '$lib/hooks',
|
|
107
|
+
lib: '$lib'
|
|
128
108
|
},
|
|
129
109
|
typescript: false
|
|
130
110
|
};
|
|
@@ -166,7 +146,7 @@ export function cn(...inputs) {
|
|
|
166
146
|
export function configureCss(projectPath, includeFonts) {
|
|
167
147
|
let css = '';
|
|
168
148
|
if (includeFonts) {
|
|
169
|
-
css += '@import "
|
|
149
|
+
css += '@import "./fonts.css";\n';
|
|
170
150
|
}
|
|
171
151
|
css += '@import "@archetypeai/ds-lib-tokens/theme.css";\n';
|
|
172
152
|
css += '@import "tailwindcss";\n';
|
|
@@ -211,7 +191,7 @@ export function prependCss(projectPath, includeFonts) {
|
|
|
211
191
|
|
|
212
192
|
let imports = '';
|
|
213
193
|
if (includeFonts) {
|
|
214
|
-
imports += '@import "
|
|
194
|
+
imports += '@import "./fonts.css";\n';
|
|
215
195
|
}
|
|
216
196
|
imports += '@import "@archetypeai/ds-lib-tokens/theme.css";\n';
|
|
217
197
|
imports += '@import "tailwindcss";\n';
|
|
@@ -235,9 +215,7 @@ export async function installComponents(pm, projectPath, componentUrls) {
|
|
|
235
215
|
await run(
|
|
236
216
|
dlxCmd,
|
|
237
217
|
[...dlxArgs, 'shadcn-svelte@latest', 'add', ...urls, '--yes', '--overwrite'],
|
|
238
|
-
{
|
|
239
|
-
cwd: projectPath
|
|
240
|
-
}
|
|
218
|
+
{ cwd: projectPath }
|
|
241
219
|
);
|
|
242
220
|
|
|
243
221
|
const [installCmd, ...installArgs] = splitCmd(pm.install);
|