synthesisui 0.1.18 → 0.1.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/dist/commands/use.js +95 -0
- package/dist/index.js +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readProjectConfig } from "../config.js";
|
|
4
|
+
async function readRootLock(path) {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async function exists(path) {
|
|
13
|
+
try {
|
|
14
|
+
await access(path);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `synthesisui use <slug> "<intent>"` - the platform↔app bridge (INS-10).
|
|
23
|
+
*
|
|
24
|
+
* Reads only LOCAL state (the installed `.lock`, the project `config.json`, and
|
|
25
|
+
* which guidance files exist) and prints a ready-to-paste prompt for your coding
|
|
26
|
+
* agent (Claude Code, Cursor, …) describing the task **on-system**: which files
|
|
27
|
+
* to read first, the scope attribute, the styling contract, and where files go.
|
|
28
|
+
* Works for both *bringing in* new UI ("a pricing section with 3 tiers") and
|
|
29
|
+
* *modifying* existing UI ("make the card shadow softer in components/Card.tsx").
|
|
30
|
+
*
|
|
31
|
+
* No network: the DS must already be installed (`synthesisui add <slug>`).
|
|
32
|
+
*/
|
|
33
|
+
export async function use(slug, intent, opts) {
|
|
34
|
+
const root = opts.dir ?? process.cwd();
|
|
35
|
+
const slugDir = join(root, "_synthesisui", "ds", slug);
|
|
36
|
+
const lock = await readRootLock(join(slugDir, ".lock"));
|
|
37
|
+
if (!lock) {
|
|
38
|
+
console.error(`error: "${slug}" is not installed in this project.\n` +
|
|
39
|
+
` run \`synthesisui add ${slug}\` first (brings tokens.css + GUIDE.md), then retry.`);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const config = await readProjectConfig(root);
|
|
44
|
+
const { version, name } = lock;
|
|
45
|
+
const base = `_synthesisui/ds/${slug}`;
|
|
46
|
+
// Highest-authority guidance first; only list files that actually exist.
|
|
47
|
+
const hasRules = await exists(join(slugDir, "rules.md"));
|
|
48
|
+
const hasPhilosophy = await exists(join(slugDir, "philosophy.md"));
|
|
49
|
+
const readFirst = [
|
|
50
|
+
hasRules
|
|
51
|
+
? `- ${base}/rules.md — project rules for this system; obey them above everything else`
|
|
52
|
+
: "",
|
|
53
|
+
hasPhilosophy
|
|
54
|
+
? `- ${base}/philosophy.md — the mission, voice and principles; let it shape every screen`
|
|
55
|
+
: "",
|
|
56
|
+
`- ${base}/v${version}/GUIDE.md — how to apply the system, the recipes and the token vocabulary`,
|
|
57
|
+
].filter(Boolean);
|
|
58
|
+
// The styling contract differs by target: Next projects in this product use
|
|
59
|
+
// Tailwind v4 backed by the DS; the "general" target is framework-agnostic CSS.
|
|
60
|
+
const stylingRule = config.target === "general"
|
|
61
|
+
? `- Style with the design system only: reuse the \`.ds-*\` recipe classes and the ` +
|
|
62
|
+
`\`var(--ds-*)\` custom properties. Never use raw hex/px outside the system's scale.`
|
|
63
|
+
: `- Style with the design system only: reuse the \`.ds-*\` recipe classes and the ` +
|
|
64
|
+
`DS-backed Tailwind utilities (\`bg-primary\`, \`text-foreground\`, \`p-md\`, \`rounded-lg\`, ` +
|
|
65
|
+
`\`font-display\`…). Never use raw hex/px outside the system's scale.`;
|
|
66
|
+
const task = intent.trim() || "build the UI I describe next";
|
|
67
|
+
const prompt = [
|
|
68
|
+
`Use the "${name}" design system (slug: ${slug}, v${version}) to: ${task}`,
|
|
69
|
+
"",
|
|
70
|
+
"Read these files in the project first (highest authority first):",
|
|
71
|
+
...readFirst,
|
|
72
|
+
"",
|
|
73
|
+
"Follow this contract:",
|
|
74
|
+
`- Scope the markup with \`data-ds="${slug}"\` (or rely on it at the app root).`,
|
|
75
|
+
stylingRule,
|
|
76
|
+
`- Target framework: ${config.target}. Put new components in \`${config.componentsDir}/\` ` +
|
|
77
|
+
`and pages in \`${config.pagesDir}/\`.`,
|
|
78
|
+
config.target === "next"
|
|
79
|
+
? '- Make sure `tokens.css` + `theme.css` are imported in the global CSS (see the GUIDE\'s "How to apply").'
|
|
80
|
+
: '- Make sure `tokens.css` is imported in the global CSS (see the GUIDE\'s "How to apply").',
|
|
81
|
+
"- Wire the behavior yourself (open/close, focus, routing) - the system ships the looks, not the JS.",
|
|
82
|
+
"",
|
|
83
|
+
"Deliver senior-level, production-quality code: clean structure, accessible (ARIA + keyboard), and responsive.",
|
|
84
|
+
].join("\n");
|
|
85
|
+
// Framing lines go to stderr so `synthesisui use … | pbcopy` copies only the
|
|
86
|
+
// prompt itself (stdout), while the human still sees the guidance.
|
|
87
|
+
console.error(`✓ ${name} v${version} · target ${config.target}\n`);
|
|
88
|
+
console.error("Copy the prompt below and paste it to your coding agent:\n");
|
|
89
|
+
console.error("──────────────────────────────────────────────────────────");
|
|
90
|
+
console.log(prompt);
|
|
91
|
+
console.error("──────────────────────────────────────────────────────────");
|
|
92
|
+
console.error("\nTip: `synthesisui use " +
|
|
93
|
+
slug +
|
|
94
|
+
' "…" | pbcopy` (macOS) copies just the prompt.');
|
|
95
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { init } from "./commands/init.js";
|
|
|
6
6
|
import { list } from "./commands/list.js";
|
|
7
7
|
import { login } from "./commands/login.js";
|
|
8
8
|
import { page } from "./commands/page.js";
|
|
9
|
+
import { use } from "./commands/use.js";
|
|
9
10
|
import { RegistryError } from "./registry.js";
|
|
10
11
|
const HELP = `synthesisui - bring SynthesisUI design systems into your project
|
|
11
12
|
|
|
@@ -15,6 +16,7 @@ Usage:
|
|
|
15
16
|
synthesisui list [options] list the published design systems
|
|
16
17
|
synthesisui add <slug> [options] materialize a DS into _synthesisui/ds/<slug>/
|
|
17
18
|
synthesisui page <slug> <template> materialize a whole page from a DS template
|
|
19
|
+
synthesisui use <slug> "<intent>" print a ready-to-paste agent prompt to build/modify on-system
|
|
18
20
|
synthesisui advise "<value prop>" engagement-pattern proposals for this project (login required)
|
|
19
21
|
synthesisui generate "<desc>" generate a token-only component recipe for your DS (login required)
|
|
20
22
|
|
|
@@ -39,6 +41,8 @@ Examples:
|
|
|
39
41
|
synthesisui add halogen --version 3
|
|
40
42
|
synthesisui page halogen dashboard-sidebar
|
|
41
43
|
synthesisui page halogen landing --out app/page.tsx
|
|
44
|
+
synthesisui use halogen "a pricing section with three tiers and a highlighted plan"
|
|
45
|
+
synthesisui use halogen "make the card shadow softer in components/StatCard.tsx"
|
|
42
46
|
synthesisui advise "habit-building app for tracking personal finances"
|
|
43
47
|
synthesisui generate "an upgrade banner with a title, message and a primary CTA"
|
|
44
48
|
`;
|
|
@@ -143,6 +147,17 @@ async function main() {
|
|
|
143
147
|
await page(slug, template, { registry, dir, out, target, version });
|
|
144
148
|
break;
|
|
145
149
|
}
|
|
150
|
+
case "use": {
|
|
151
|
+
const slug = args[0];
|
|
152
|
+
if (!slug) {
|
|
153
|
+
console.error('error: provide the slug and your intent - `synthesisui use <slug> "<intent>"`');
|
|
154
|
+
process.exitCode = 1;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const intent = args.slice(1).join(" ").trim();
|
|
158
|
+
await use(slug, intent, { dir });
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
146
161
|
case "advise": {
|
|
147
162
|
const valueProp = args.join(" ").trim();
|
|
148
163
|
if (!valueProp) {
|