create-forte-ui 1.0.0-alpha.4 → 1.0.0-alpha.5

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/args.d.ts CHANGED
@@ -6,8 +6,19 @@ export type CliOptions = {
6
6
  framework?: Framework;
7
7
  tailwind?: boolean;
8
8
  pm?: PackageManager;
9
+ /** Version spec for `@forte-ui/react` — exact ("1.0.0-alpha.4"), dist-tag
10
+ * ("alpha"), or range. Deliberately NOT validated here: the package
11
+ * manager understands every legal form (tags, ranges, `file:`…) and
12
+ * rejects a wrong one at install with a better error than any regex
13
+ * would give. Undefined = the registry's `latest`. Dev/CI knob only —
14
+ * no prompt, and the studio dialog knows nothing about it. */
15
+ library?: string;
9
16
  yes: boolean;
10
17
  install: boolean;
18
+ /** Install the forte-ui agent skill (skills.sh) into the project. On by
19
+ * default; `--no-skill` opts out, and `--no-install` skips it with
20
+ * everything else. */
21
+ skill: boolean;
11
22
  help: boolean;
12
23
  version: boolean;
13
24
  /** Only the keys given as flags — presence is what suppresses the prompt. */
@@ -16,4 +27,4 @@ export type CliOptions = {
16
27
  export declare class UsageError extends Error {
17
28
  }
18
29
  export declare function parseCliArgs(argv: string[]): CliOptions;
19
- export declare const HELP = "create-forte-ui \u2014 scaffold a new app wired up with forte-ui\n\nUsage\n pnpm create forte-ui [name] [flags]\n npm create forte-ui@latest [name] -- [flags]\n\nEvery flag has a prompt twin; a passed flag suppresses its prompt. With no\nflags you get the questionnaire, with --yes you get a Next.js + Tailwind app\non the library's default theme.\n\nProject\n [name] project directory (prompted if omitted)\n -f, --framework next | vite\n --tailwind wire the Tailwind v4 bridge (default yes)\n --no-tailwind plain CSS setup\n --pm npm | pnpm | yarn | bun (default: whoever invoked us)\n --no-install write files only; skip installing dependencies\n -y, --yes accept the defaults for everything not passed\n\nTheme \u2014 every skipped value keeps the library default and writes NOTHING,\nso the app keeps following the library when defaults are tuned.\n --seed, --accent accent seed, hex (\"#6d43d4\")\n --secondary secondary seed, hex\n --tint neutral tint, 0 (pure grey) to 1 (default)\n --radius none | soft | pill\n --density compact | spacious\n --motion system (default) | reduce | full\n \"full\" overrides the OS reduced-motion preference\n for everyone \u2014 prefer leaving it unset.\n --font-sans a catalogue name (\"Inter\", \"DM Sans\", ...)\n --font-mono a catalogue name (\"JetBrains Mono\", ...)\n\nDesign the theme visually instead: https://forte-ui.com/theme\n";
30
+ export declare const HELP = "create-forte-ui \u2014 scaffold a new app wired up with forte-ui\n\nUsage\n pnpm create forte-ui [name] [flags]\n npm create forte-ui@latest [name] -- [flags]\n\nEvery flag has a prompt twin; a passed flag suppresses its prompt. With no\nflags you get the questionnaire, with --yes you get a Next.js + Tailwind app\non the library's default theme.\n\nProject\n [name] project directory (prompted if omitted)\n -f, --framework next | vite\n --tailwind wire the Tailwind v4 bridge (default yes)\n --no-tailwind plain CSS setup\n --pm npm | pnpm | yarn | bun (default: whoever invoked us)\n --library version spec for @forte-ui/react \u2014 exact\n (\"1.0.0-alpha.4\"), a dist-tag (\"alpha\"), or a range.\n Default: latest.\n --no-install write files only; skip installing dependencies\n and the agent skill\n --no-skill skip installing the forte-ui agent skill\n (skills.sh \u2014 .agents/skills plus .claude/skills)\n -y, --yes accept the defaults for everything not passed\n\nTheme \u2014 every skipped value keeps the library default and writes NOTHING,\nso the app keeps following the library when defaults are tuned.\n --seed, --accent accent seed, hex (\"#6d43d4\")\n --secondary secondary seed, hex\n --tint neutral tint, 0 (pure grey) to 1 (default)\n --radius none | soft | pill\n --density compact | spacious\n --motion system (default) | reduce | full\n \"full\" overrides the OS reduced-motion preference\n for everyone \u2014 prefer leaving it unset.\n --font-sans a catalogue name (\"Inter\", \"DM Sans\", ...)\n --font-mono a catalogue name (\"JetBrains Mono\", ...)\n\nDesign the theme visually instead: https://forte-ui.com/theme\n";
package/dist/args.js CHANGED
@@ -53,9 +53,11 @@ export function parseCliArgs(argv) {
53
53
  motion: { type: "string" },
54
54
  "font-sans": { type: "string" },
55
55
  "font-mono": { type: "string" },
56
+ library: { type: "string" },
56
57
  pm: { type: "string" },
57
58
  yes: { type: "boolean", short: "y" },
58
59
  "no-install": { type: "boolean" },
60
+ "no-skill": { type: "boolean" },
59
61
  help: { type: "boolean", short: "h" },
60
62
  version: { type: "boolean", short: "v" },
61
63
  },
@@ -103,8 +105,10 @@ export function parseCliArgs(argv) {
103
105
  framework: values.framework === undefined ? undefined : oneOf("framework", values.framework, ["next", "vite"]),
104
106
  tailwind: values.tailwind ? true : values["no-tailwind"] ? false : undefined,
105
107
  pm: values.pm === undefined ? undefined : oneOf("pm", values.pm, PACKAGE_MANAGERS),
108
+ library: values.library,
106
109
  yes: values.yes ?? false,
107
110
  install: !(values["no-install"] ?? false),
111
+ skill: !(values["no-skill"] ?? false),
108
112
  help: values.help ?? false,
109
113
  version: values.version ?? false,
110
114
  answers,
@@ -126,7 +130,13 @@ Project
126
130
  --tailwind wire the Tailwind v4 bridge (default yes)
127
131
  --no-tailwind plain CSS setup
128
132
  --pm npm | pnpm | yarn | bun (default: whoever invoked us)
133
+ --library version spec for @forte-ui/react — exact
134
+ ("1.0.0-alpha.4"), a dist-tag ("alpha"), or a range.
135
+ Default: latest.
129
136
  --no-install write files only; skip installing dependencies
137
+ and the agent skill
138
+ --no-skill skip installing the forte-ui agent skill
139
+ (skills.sh — .agents/skills plus .claude/skills)
130
140
  -y, --yes accept the defaults for everything not passed
131
141
 
132
142
  Theme — every skipped value keeps the library default and writes NOTHING,
package/dist/index.js CHANGED
@@ -15,8 +15,8 @@ import pc from "picocolors";
15
15
  import { parseCliArgs, UsageError, HELP } from "./args.js";
16
16
  import { collectPlan } from "./prompts.js";
17
17
  import { hexToOklch, validateSeed } from "./color.js";
18
- import { applyOverlay, dependenciesFor, recordDependencies } from "./overlay.js";
19
- import { detectPackageManager, runScaffolder, addDependencies, devCommand, installCommand, } from "./scaffold.js";
18
+ import { applyOverlay, dependenciesFor, recordDependencies, toAddSpecs, } from "./overlay.js";
19
+ import { detectPackageManager, runScaffolder, addDependencies, installSkill, devCommand, installCommand, } from "./scaffold.js";
20
20
  function ownVersion() {
21
21
  const pkgPath = path.join(fileURLToPath(import.meta.url), "../../package.json");
22
22
  return JSON.parse(fs.readFileSync(pkgPath, "utf8")).version;
@@ -109,17 +109,35 @@ async function main() {
109
109
  process.exit(1);
110
110
  }
111
111
  p.log.success(`Wired up forte-ui: ${written.join(", ")}`);
112
- const deps = dependenciesFor(plan);
112
+ const deps = dependenciesFor(plan, opts.library);
113
+ const specs = toAddSpecs(deps);
113
114
  if (opts.install) {
114
- p.log.step(`Installing ${deps.join(", ")} with ${pm}…`);
115
- if (!addDependencies(pm, deps, plan.dir)) {
116
- p.cancel(`${pm} failed to install run ${pc.bold(`${installCommand(pm)}`)} in ./${plan.name} yourself.`);
115
+ p.log.step(`Installing ${specs.join(", ")} with ${pm}…`);
116
+ if (!addDependencies(pm, specs, plan.dir)) {
117
+ /* A `--library` spec is validated only here, by the registry itself —
118
+ * so on failure say which spec died rather than suggesting a re-run
119
+ * that would resolve the exact same thing. */
120
+ p.cancel(opts.library
121
+ ? `${pm} could not install @forte-ui/react@${opts.library} — see its output above. ` +
122
+ `Check that the --library spec exists on the registry.`
123
+ : `${pm} failed to install — run ${pc.bold(`${installCommand(pm)}`)} in ./${plan.name} yourself.`);
117
124
  process.exit(1);
118
125
  }
119
126
  }
120
127
  else {
121
128
  recordDependencies(plan.dir, deps);
122
- p.log.info(`Skipped install; added ${deps.join(", ")} to package.json.`);
129
+ p.log.info(`Skipped install; added ${specs.join(", ")} to package.json.`);
130
+ }
131
+ /* The agent skill, so AI tooling in the new project starts past the
132
+ * library's silent traps. Gated on `install` too: `--no-install` means
133
+ * "write files, run nothing". Failure is a warning, not an exit — the app
134
+ * is complete without it, and the guide's one-liner recovers it. */
135
+ if (opts.install && opts.skill) {
136
+ p.log.step("Installing the forte-ui agent skill…");
137
+ if (!installSkill(pm, plan.dir)) {
138
+ p.log.warn("Skill install failed — the app is unaffected. " +
139
+ `Run ${pc.bold("npx skills add arsen/forte-ui -s forte-ui")} in ./${plan.name} to retry.`);
140
+ }
123
141
  }
124
142
  const steps = [
125
143
  `cd ${plan.name}`,
package/dist/overlay.d.ts CHANGED
@@ -9,8 +9,16 @@ export type ProjectPlan = {
9
9
  };
10
10
  /** Returns the files it wrote (project-relative), for the summary. */
11
11
  export declare function applyOverlay(plan: ProjectPlan): string[];
12
+ export type Dependency = {
13
+ name: string;
14
+ spec: string;
15
+ };
12
16
  /** The `--no-install` fallback: record the dependencies so the user's own
13
- * install resolves them. "latest" is a dist-tag, which every manager
14
- * accepts and replaces with a real range on first install. */
15
- export declare function recordDependencies(dir: string, deps: string[]): void;
16
- export declare function dependenciesFor(plan: ProjectPlan): string[];
17
+ * install resolves them. The default spec is the "latest" dist-tag, which
18
+ * every manager accepts and replaces with a real range on first install
19
+ * and so is anything `--library` put there instead, tag, range or exact. */
20
+ export declare function recordDependencies(dir: string, deps: Dependency[]): void;
21
+ /** `pm add` arguments: the bare name resolves `latest` exactly as before, so
22
+ * only a `--library` spec changes what gets asked of the registry. */
23
+ export declare function toAddSpecs(deps: Dependency[]): string[];
24
+ export declare function dependenciesFor(plan: ProjectPlan, library?: string): Dependency[];
package/dist/overlay.js CHANGED
@@ -88,20 +88,28 @@ function applyNext({ name, dir, tailwind, answers }) {
88
88
  return written;
89
89
  }
90
90
  /** The `--no-install` fallback: record the dependencies so the user's own
91
- * install resolves them. "latest" is a dist-tag, which every manager
92
- * accepts and replaces with a real range on first install. */
91
+ * install resolves them. The default spec is the "latest" dist-tag, which
92
+ * every manager accepts and replaces with a real range on first install
93
+ * and so is anything `--library` put there instead, tag, range or exact. */
93
94
  export function recordDependencies(dir, deps) {
94
95
  const pkgPath = path.join(dir, "package.json");
95
96
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
96
97
  pkg.dependencies ??= {};
97
98
  for (const dep of deps)
98
- pkg.dependencies[dep] = "latest";
99
+ pkg.dependencies[dep.name] = dep.spec;
99
100
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
100
101
  }
101
- export function dependenciesFor(plan) {
102
- /* create-next-app's --tailwind scaffold already carries tailwindcss v4;
103
- * on Vite the guide installs it alongside the library, plus the plugin. */
102
+ /** `pm add` arguments: the bare name resolves `latest` exactly as before, so
103
+ * only a `--library` spec changes what gets asked of the registry. */
104
+ export function toAddSpecs(deps) {
105
+ return deps.map((d) => (d.spec === "latest" ? d.name : `${d.name}@${d.spec}`));
106
+ }
107
+ export function dependenciesFor(plan, library) {
108
+ /* `--library` steers ONLY the library. The Vite Tailwind extras stay on
109
+ * latest — the templates target current Tailwind v4 regardless of which
110
+ * forte-ui build is being tried out. */
111
+ const lib = { name: "@forte-ui/react", spec: library ?? "latest" };
104
112
  return plan.framework === "vite" && plan.tailwind
105
- ? ["@forte-ui/react", "tailwindcss", "@tailwindcss/vite"]
106
- : ["@forte-ui/react"];
113
+ ? [lib, { name: "tailwindcss", spec: "latest" }, { name: "@tailwindcss/vite", spec: "latest" }]
114
+ : [lib];
107
115
  }
@@ -12,6 +12,13 @@ export declare function runScaffolder(pm: PackageManager, pkg: string, args: str
12
12
  /** `pm add <deps>` in the project — resolves "latest" into a real caret range
13
13
  * in package.json and performs the full install in one pass. */
14
14
  export declare function addDependencies(pm: PackageManager, deps: string[], cwd: string): boolean;
15
+ /** Install the forte-ui agent skill into the project via skills.sh, the
16
+ * same command the AI-agents guide documents. `-s forte-ui` is load-bearing:
17
+ * the repository also carries internal skills (release-prep) that must not
18
+ * reach consumers. `-y` writes the universal `.agents/skills` copy plus the
19
+ * per-agent links — `.claude/skills` for Claude Code among them — without
20
+ * prompting. */
21
+ export declare function installSkill(pm: PackageManager, cwd: string): boolean;
15
22
  /** The dev-server line for the outro, in the user's own manager. */
16
23
  export declare function devCommand(pm: PackageManager): string;
17
24
  export declare function installCommand(pm: PackageManager): string;
package/dist/scaffold.js CHANGED
@@ -46,6 +46,15 @@ export function addDependencies(pm, deps, cwd) {
46
46
  const sub = pm === "npm" ? "install" : "add";
47
47
  return run(pm, [sub, ...deps], cwd);
48
48
  }
49
+ /** Install the forte-ui agent skill into the project via skills.sh, the
50
+ * same command the AI-agents guide documents. `-s forte-ui` is load-bearing:
51
+ * the repository also carries internal skills (release-prep) that must not
52
+ * reach consumers. `-y` writes the universal `.agents/skills` copy plus the
53
+ * per-agent links — `.claude/skills` for Claude Code among them — without
54
+ * prompting. */
55
+ export function installSkill(pm, cwd) {
56
+ return runScaffolder(pm, "skills@latest", ["add", "arsen/forte-ui", "-s", "forte-ui", "-y"], cwd);
57
+ }
49
58
  /** The dev-server line for the outro, in the user's own manager. */
50
59
  export function devCommand(pm) {
51
60
  return pm === "npm" ? "npm run dev" : `${pm} dev`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-forte-ui",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "Scaffold a new app wired up with forte-ui — Vite or Next.js, with or without Tailwind, themed from your answers.",
5
5
  "license": "MIT",
6
6
  "type": "module",