@archetypeai/ds-cli 0.3.16 → 0.3.18
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 +16 -0
- package/files/CLAUDE.md +15 -1
- package/files/rules/charts.md +1 -97
- package/files/rules/components.md +1 -16
- package/files/rules/design-principles.md +16 -1
- package/files/rules/frontend-architecture.md +11 -0
- package/files/rules/state.md +2 -34
- package/files/rules/styling.md +24 -119
- package/files/skills/build-pattern/SKILL.md +2 -0
- package/files/skills/create-dashboard/SKILL.md +22 -3
- package/files/skills/embedding-from-file/SKILL.md +14 -1
- package/files/skills/embedding-from-sensor/SKILL.md +14 -1
- package/files/skills/embedding-upload/SKILL.md +14 -1
- package/files/skills/newton-activity-monitor-lens-on-video/SKILL.md +1 -1
- package/files/skills/newton-camera-frame-analysis/SKILL.md +14 -1
- package/files/skills/newton-direct-query/SKILL.md +9 -0
- package/files/skills/newton-machine-state-from-file/SKILL.md +15 -1
- package/files/skills/newton-machine-state-from-sensor/SKILL.md +15 -1
- package/lib/install-fonts-local.js +212 -0
- package/lib/is-interactive.js +0 -9
- package/lib/scaffold-ds-svelte-project.js +31 -28
- package/package.json +1 -1
|
@@ -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
|
-
}
|
|
@@ -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();
|
|
@@ -166,7 +149,7 @@ export function cn(...inputs) {
|
|
|
166
149
|
export function configureCss(projectPath, includeFonts) {
|
|
167
150
|
let css = '';
|
|
168
151
|
if (includeFonts) {
|
|
169
|
-
css += '@import "
|
|
152
|
+
css += '@import "./fonts.css";\n';
|
|
170
153
|
}
|
|
171
154
|
css += '@import "@archetypeai/ds-lib-tokens/theme.css";\n';
|
|
172
155
|
css += '@import "tailwindcss";\n';
|
|
@@ -211,7 +194,7 @@ export function prependCss(projectPath, includeFonts) {
|
|
|
211
194
|
|
|
212
195
|
let imports = '';
|
|
213
196
|
if (includeFonts) {
|
|
214
|
-
imports += '@import "
|
|
197
|
+
imports += '@import "./fonts.css";\n';
|
|
215
198
|
}
|
|
216
199
|
imports += '@import "@archetypeai/ds-lib-tokens/theme.css";\n';
|
|
217
200
|
imports += '@import "tailwindcss";\n';
|
|
@@ -256,20 +239,40 @@ export async function installComponents(pm, projectPath, componentUrls) {
|
|
|
256
239
|
}
|
|
257
240
|
}
|
|
258
241
|
|
|
259
|
-
// add a demo page with
|
|
242
|
+
// add a demo page with design system examples to app
|
|
260
243
|
export function createDemoPage(projectPath) {
|
|
261
244
|
const pagePath = join(projectPath, 'src/routes/+page.svelte');
|
|
262
245
|
const demoContent = `<script>
|
|
263
|
-
\timport
|
|
246
|
+
\timport Menubar from '$lib/components/ui/patterns/menubar/index.js';
|
|
247
|
+
\timport { Button } from '$lib/components/ui/primitives/button/index.js';
|
|
248
|
+
\timport BackgroundCard from '$lib/components/ui/patterns/background-card/index.js';
|
|
249
|
+
\timport ActivityIcon from '@lucide/svelte/icons/activity';
|
|
250
|
+
\timport CpuIcon from '@lucide/svelte/icons/cpu';
|
|
251
|
+
\timport GaugeIcon from '@lucide/svelte/icons/gauge';
|
|
252
|
+
\timport ThermometerIcon from '@lucide/svelte/icons/thermometer';
|
|
264
253
|
</script>
|
|
265
254
|
|
|
266
|
-
<div
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
255
|
+
<div
|
|
256
|
+
\tclass="bg-background text-foreground grid h-screen w-screen grid-rows-[auto_1fr] overflow-hidden"
|
|
257
|
+
>
|
|
258
|
+
\t<Menubar>
|
|
259
|
+
\t\t<Button variant="link" class="text-muted-foreground">Send Report</Button>
|
|
260
|
+
\t</Menubar>
|
|
261
|
+
|
|
262
|
+
\t<main class="grid grid-cols-2 grid-rows-2 gap-4 overflow-hidden p-4">
|
|
263
|
+
\t\t<BackgroundCard title="Panel 1" icon={ActivityIcon} class="max-h-full">
|
|
264
|
+
\t\t\t<p class="text-muted-foreground text-sm">Placeholder content</p>
|
|
265
|
+
\t\t</BackgroundCard>
|
|
266
|
+
\t\t<BackgroundCard title="Panel 2" icon={CpuIcon} class="max-h-full">
|
|
267
|
+
\t\t\t<p class="text-muted-foreground text-sm">Placeholder content</p>
|
|
268
|
+
\t\t</BackgroundCard>
|
|
269
|
+
\t\t<BackgroundCard title="Panel 3" icon={GaugeIcon} class="max-h-full">
|
|
270
|
+
\t\t\t<p class="text-muted-foreground text-sm">Placeholder content</p>
|
|
271
|
+
\t\t</BackgroundCard>
|
|
272
|
+
\t\t<BackgroundCard title="Panel 4" icon={ThermometerIcon} class="max-h-full">
|
|
273
|
+
\t\t\t<p class="text-muted-foreground text-sm">Placeholder content</p>
|
|
274
|
+
\t\t</BackgroundCard>
|
|
275
|
+
\t</main>
|
|
273
276
|
</div>
|
|
274
277
|
`;
|
|
275
278
|
writeFile(pagePath, demoContent);
|