@kondeio/kdf 0.1.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 (59) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/CONTRIBUTING.md +57 -0
  3. package/LICENSE +21 -0
  4. package/README.md +374 -0
  5. package/SECURITY.md +53 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +58 -0
  8. package/dist/css-generator.d.ts +17 -0
  9. package/dist/css-generator.js +59 -0
  10. package/dist/index.d.ts +48 -0
  11. package/dist/index.js +62 -0
  12. package/dist/plugin.d.ts +30 -0
  13. package/dist/plugin.js +40 -0
  14. package/dist/postinstall.d.ts +1 -0
  15. package/dist/postinstall.js +48 -0
  16. package/dist/resolver.d.ts +11 -0
  17. package/dist/resolver.js +184 -0
  18. package/dist/types.d.ts +44 -0
  19. package/dist/types.js +1 -0
  20. package/docs/kdf-doc.md +653 -0
  21. package/docs/kdf-skill.md +374 -0
  22. package/example/bootstrap/globals.css +12 -0
  23. package/example/bootstrap/hero-section.tsx +38 -0
  24. package/example/bootstrap/kdf/homepage.json +35 -0
  25. package/example/bootstrap/kdf/shared/button.json +10 -0
  26. package/example/bootstrap/kdf/shared/card.json +4 -0
  27. package/example/bootstrap/kdf/shared/color.json +17 -0
  28. package/example/bootstrap/kdf/shared/layout.json +7 -0
  29. package/example/bootstrap/kdf/shared/typography.json +8 -0
  30. package/example/bootstrap/konde-server.css +3 -0
  31. package/example/bootstrap/konde.css +3 -0
  32. package/example/preview.ts +428 -0
  33. package/example/pure-css/hero-section.tsx +40 -0
  34. package/example/pure-css/kdf/homepage.json +20 -0
  35. package/example/pure-css/kdf/shared/button.json +10 -0
  36. package/example/pure-css/kdf/shared/card.json +4 -0
  37. package/example/pure-css/kdf/shared/color.json +11 -0
  38. package/example/pure-css/kdf/shared/typography.json +8 -0
  39. package/example/pure-css/konde-server.css +3 -0
  40. package/example/pure-css/konde.css +3 -0
  41. package/example/pure-css/styles.css +34 -0
  42. package/example/sample-pages/about.json +30 -0
  43. package/example/sample-pages/dashboard.json +12 -0
  44. package/example/sample-pages/pricing.json +28 -0
  45. package/example/shadcn/globals.css +15 -0
  46. package/example/shadcn/hero-section.tsx +34 -0
  47. package/example/shadcn/konde-server.css +3 -0
  48. package/example/shadcn/konde.css +3 -0
  49. package/example/tailwind/globals.css +5 -0
  50. package/example/tailwind/hero-section.tsx +34 -0
  51. package/example/tailwind/konde-server.css +3 -0
  52. package/example/tailwind/konde.css +3 -0
  53. package/kdf/homepage.json +25 -0
  54. package/kdf/shared/button.json +10 -0
  55. package/kdf/shared/card.json +4 -0
  56. package/kdf/shared/color.json +17 -0
  57. package/kdf/shared/layout.json +7 -0
  58. package/kdf/shared/typography.json +8 -0
  59. package/package.json +77 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to KDF are documented here. Format loosely follows
4
+ [Keep a Changelog](https://keepachangelog.com); versions follow semver.
5
+
6
+ ## [0.1.0] - 2026-06-18
7
+
8
+ Initial public release candidate.
9
+
10
+ ### Changed
11
+ - **Class composition is now UI-library agnostic.** `cn()` / `cx()` /
12
+ `composeClasses()` normalize and dedupe exact duplicate classes by default,
13
+ while `createClassComposer({ merge })` allows app-defined semantic merge
14
+ rules without adding framework-specific runtime dependencies to KDF.
15
+ - Package scope renamed `@konde/kdf` → `@kondeio/kdf`.
16
+ - `package.json` description clarified: KDF is a Node/server-side package with
17
+ an optional Next.js plugin and UI-library agnostic class composition.
18
+
19
+ ### Added
20
+ - `dedupeClasses()`, `composeClasses()`, `cx()`, and
21
+ `createClassComposer({ merge })`.
22
+ - Documented the **server-only** constraint (resolver uses Node `fs`) across
23
+ README, `docs/kdf-doc.md`, and `docs/kdf-skill.md`, with the
24
+ resolve-on-server / pass-className-as-prop pattern.
25
+ - `CONTRIBUTING.md`, `SECURITY.md`, `CHANGELOG.md`.
26
+
27
+ ### Fixed
28
+ - `@ref` component names are validated against `^[A-Za-z0-9_-]+$` — path-traversal
29
+ references (`..`, separators) are rejected instead of resolving to arbitrary
30
+ `.json` files.
31
+ - Corrected the plugin "auto-inject CSS" claim: `withKDF()` only exposes paths
32
+ via env (`KDF_DIR`, `KDF_SERVER_CSS`, `KDF_CLIENT_CSS`); the host app wires the
33
+ stylesheet.
@@ -0,0 +1,57 @@
1
+ # Contributing to KDF
2
+
3
+ Thanks for your interest in improving the Konde Design Framework.
4
+
5
+ ## Local setup
6
+
7
+ KDF builds with [Bun](https://bun.sh) (Node 18+ also works for running `dist`).
8
+
9
+ ```bash
10
+ git clone https://github.com/KondeIO/kdf.git
11
+ cd kdf
12
+ bun install
13
+ ```
14
+
15
+ ## Build & verify
16
+
17
+ ```bash
18
+ bun run build # tsc -> dist/
19
+ bun run typecheck # tsc --noEmit
20
+ bun run test # unit tests
21
+ ```
22
+
23
+ A change is ready for review when `typecheck` and `test` pass and `dist/` has
24
+ been rebuilt (the published artifact lives in `dist/`).
25
+
26
+ ## Project layout
27
+
28
+ ```
29
+ src/ TypeScript source (authoritative)
30
+ dist/ Build output (tsc) — published to npm
31
+ kdf/ Starter design tokens shipped to consumers
32
+ example/ Reference usage
33
+ docs/ Concept, agent skill, and license docs
34
+ ```
35
+
36
+ ## Pull requests
37
+
38
+ - Branch off `main`; keep PRs focused on one change.
39
+ - Keep the core **UI-library agnostic** — do not add framework-specific runtime
40
+ dependencies. Class conflict rules belong in app-level
41
+ `createClassComposer({ merge })` integrations.
42
+ - The resolver is **server-only** (Node `fs`). Do not introduce browser/DOM
43
+ assumptions into `src/resolver.ts`.
44
+ - Update `CHANGELOG.md` under `## Unreleased`.
45
+ - Run `bun run build` before committing so `src` and `dist` stay in sync.
46
+
47
+ ## Conventions
48
+
49
+ - ESM only; internal imports use explicit `.js` extensions (`./resolver.js`).
50
+ - Match the existing code style (no new formatter configs in a PR).
51
+ - Add or update docs in `docs/` when behavior changes.
52
+
53
+ ## Reporting bugs
54
+
55
+ Open an issue at https://github.com/KondeIO/kdf/issues with a minimal repro.
56
+ For security issues, see [SECURITY.md](./SECURITY.md) — do **not** open a public
57
+ issue.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 konde.io
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,374 @@
1
+ # @kondeio/kdf - Konde Design Framework
2
+
3
+ Agent-first design consistency for Node-powered web apps.
4
+
5
+ KDF gives AI agents a JSON source of truth for layout, spacing, typography, and
6
+ component styling. Agents can build or update UI from that source in
7
+ server-side JavaScript apps instead of rediscovering design rules across
8
+ components, pages, and previous sessions.
9
+
10
+ Think of it like i18n for design: one page maps to one JSON file, and each
11
+ rendered element can point back to its exact design key with `data-kdf`. Users
12
+ stay in the approval loop and adjust the source only when intent or product
13
+ direction changes.
14
+
15
+ ## Why
16
+
17
+ Styling drifts when class names live only inside `.tsx` files:
18
+
19
+ - the same button slowly gets five different variants
20
+ - spacing changes page by page
21
+ - colors and typography become inconsistent
22
+ - each new AI session has to rediscover the design rules
23
+ - users spend time correcting visual drift through chat
24
+
25
+ KDF moves repeatable styling into JSON:
26
+
27
+ - agents apply tokens before changing UI
28
+ - users can review and adjust the source when needed
29
+ - `data-kdf` maps every DOM element back to its exact JSON path
30
+ - the same design key can be scanned, tested, reviewed, and edited later
31
+
32
+ KDF works with your existing styling stack: plain CSS, CSS modules, utility CSS,
33
+ Bootstrap, shadcn, or a custom design system. It is not a component library and
34
+ not a CSS engine.
35
+
36
+ ## Runtime Support
37
+
38
+ KDF core runs in Node/server-side JavaScript environments because it reads JSON
39
+ from disk with Node `fs`.
40
+
41
+ - Works with server-rendered Next.js, Astro, Hono, or similar Node runtimes.
42
+ - The included `@kondeio/kdf/plugin` export is the official Next.js integration.
43
+ - Next.js plugin target: App Router, Next.js 14+ (`next >=14`).
44
+ - `getDesign()`, `d()`, and `d.css()` are server-only. Browser/client
45
+ components cannot call them directly; resolve classes server-side and pass
46
+ class names down when needed.
47
+
48
+ | Framework | Status | How KDF is used |
49
+ | --- | --- | --- |
50
+ | Next.js | Tested | Core API in server-rendered code, plus the official `@kondeio/kdf/plugin` integration. |
51
+ | Astro | Tested | Core API in server-rendered code. |
52
+ | Hono | Tested | Core API in server handlers. |
53
+
54
+ ## Install
55
+
56
+ Install the package:
57
+
58
+ ```bash
59
+ npm install @kondeio/kdf
60
+ pnpm add @kondeio/kdf
61
+ bun add @kondeio/kdf
62
+ ```
63
+
64
+ By default, install also scaffolds a starter `kdf/` folder when one does not
65
+ already exist. Existing files are never overwritten.
66
+
67
+ To install the dependency without running the initializer:
68
+
69
+ ```bash
70
+ npm install @kondeio/kdf --ignore-scripts
71
+ ```
72
+
73
+ Run initialization manually later:
74
+
75
+ ```bash
76
+ npx kdf init
77
+ ```
78
+
79
+ `npx kdf init` uses the local package binary when `@kondeio/kdf` is already
80
+ installed in the project.
81
+
82
+ Initialize a custom design directory:
83
+
84
+ ```bash
85
+ KDF_DIR=./designs npx kdf init
86
+ ```
87
+
88
+ ## File Structure
89
+
90
+ ```
91
+ kdf/
92
+ shared/ <- shared defaults (button, typography, layout, card)
93
+ homepage.json <- starter page design
94
+ konde-server.css <- critical project overrides
95
+ konde.css <- non-critical project overrides
96
+ ```
97
+
98
+ The package repository also keeps additional page JSON examples under
99
+ `example/sample-pages/`. They are reference material only and are not copied by
100
+ `postinstall` or `kdf init`.
101
+
102
+ Typical app structure:
103
+
104
+ ```
105
+ my-app/
106
+ app/
107
+ page.tsx
108
+ pricing/page.tsx
109
+ components/
110
+ hero.tsx
111
+ pricing-table.tsx
112
+ kdf/
113
+ shared/
114
+ button.json
115
+ card.json
116
+ color.json
117
+ layout.json
118
+ typography.json
119
+ homepage.json
120
+ konde-server.css
121
+ konde.css
122
+ next.config.ts
123
+ ```
124
+
125
+ ## Custom Design Directory
126
+
127
+ The default design directory is `./kdf`.
128
+
129
+ Use `./designs` or `./design` through `KDF_DIR` in any Node/server-side runtime:
130
+
131
+ ```bash
132
+ KDF_DIR=./designs npm run dev
133
+ ```
134
+
135
+ ```tsx
136
+ import { getDesign } from "@kondeio/kdf";
137
+
138
+ const d = getDesign("homepage");
139
+ ```
140
+
141
+ In Next.js, the optional plugin sets `KDF_DIR` for the app:
142
+
143
+ ```ts
144
+ // next.config.ts
145
+ import withKDF from "@kondeio/kdf/plugin";
146
+
147
+ export default withKDF({ dir: "./designs" })(nextConfig);
148
+ ```
149
+
150
+ With that config, KDF reads:
151
+
152
+ ```text
153
+ designs/
154
+ shared/
155
+ homepage.json
156
+ konde-server.css
157
+ konde.css
158
+ ```
159
+
160
+ Example token:
161
+
162
+ ```json
163
+ {
164
+ "$layout": ["hero", "features", "footer"],
165
+ "hero": {
166
+ "wrapper": "mx-auto max-w-6xl px-6 py-20",
167
+ "title": "@typography.h1",
168
+ "cta": "@button.cta"
169
+ }
170
+ }
171
+ ```
172
+
173
+ ## Usage
174
+
175
+ ```tsx
176
+ import { getDesign } from "@kondeio/kdf";
177
+
178
+ const d = getDesign("homepage");
179
+
180
+ <h1 data-kdf="hero.title" className={d("hero.title")}>
181
+ {t("hero.headline")}
182
+ </h1>
183
+ ```
184
+
185
+ ## Class Composition
186
+
187
+ KDF includes small class composition helpers that work with any UI library:
188
+
189
+ | Helper | Purpose |
190
+ | --- | --- |
191
+ | `cn()` | Joins conditional classes, drops falsy values, normalizes whitespace, and removes exact duplicates. |
192
+ | `cx()` | Alias of `cn()`. |
193
+ | `composeClasses()` | Same default composer with a more explicit name. |
194
+ | `dedupeClasses()` | Removes exact duplicates from an existing class string. |
195
+ | `createClassComposer({ merge })` | Creates a composer with an app-defined merge step. |
196
+
197
+ The default behavior is intentionally universal. It normalizes whitespace and
198
+ dedupes exact class names, but does not interpret semantic conflicts such as
199
+ color, spacing, variant, or framework-specific utility groups.
200
+
201
+ ```tsx
202
+ import { cn, getDesign } from "@kondeio/kdf";
203
+
204
+ const d = getDesign("homepage");
205
+
206
+ <button
207
+ data-kdf="hero.cta"
208
+ className={cn(d("hero.cta"), isActive && d("hero.cta-active"), className)}
209
+ >
210
+ Start
211
+ </button>
212
+ ```
213
+
214
+ Remove exact duplicates:
215
+
216
+ ```ts
217
+ import { dedupeClasses } from "@kondeio/kdf";
218
+
219
+ dedupeClasses("btn btn btn-primary");
220
+ // "btn btn-primary"
221
+ ```
222
+
223
+ Add project-specific merge rules:
224
+
225
+ ```ts
226
+ import { createClassComposer } from "@kondeio/kdf";
227
+
228
+ const cn = createClassComposer({
229
+ merge(className) {
230
+ // Example: apply project-specific class rules here.
231
+ return className;
232
+ },
233
+ });
234
+ ```
235
+
236
+ ## Server-only
237
+
238
+ `getDesign()`, `d()`, and `d.css()` read JSON from disk via Node `fs`, so they
239
+ run on the **server only**: Next.js Server Components, Astro server rendering,
240
+ Hono handlers, or equivalent Node/server-rendered code. They do **not** work
241
+ inside browser-only code or a Next.js Client Component (`"use client"`), which
242
+ has no filesystem.
243
+
244
+ For client components, resolve on the server and pass the resulting className
245
+ string down as a prop:
246
+
247
+ ```tsx
248
+ // Server Component
249
+ const d = getDesign("homepage");
250
+ return <ClientThing className={d("hero.cta")} />;
251
+ ```
252
+
253
+ ## References
254
+
255
+ Reference shared tokens from shared/:
256
+
257
+ ```json
258
+ { "hero": { "cta": "@button.cta" } }
259
+ ```
260
+
261
+ Extend with extra classes:
262
+
263
+ ```json
264
+ { "hero": { "cta": "@button.cta shadow-xl text-lg" } }
265
+ ```
266
+
267
+ Multiple refs:
268
+
269
+ ```json
270
+ { "hero": { "login": "@button.base @button.ghost @button.sm" } }
271
+ ```
272
+
273
+ ## `data-kdf`
274
+
275
+ Every element using `d()` should have matching `data-kdf`:
276
+
277
+ ```tsx
278
+ <div data-kdf="hero.wrapper" className={d("hero.wrapper")}>
279
+ ```
280
+
281
+ This makes the rendered UI traceable for agent scanning, visual editing, and
282
+ Playwright checks.
283
+
284
+ ## Cache Behavior
285
+
286
+ KDF caches design JSON files by default. In development it revalidates with
287
+ file `mtime`/`size` checks so repeated `d()` calls do not create disk-read
288
+ storms during HMR.
289
+
290
+ ```tsx
291
+ const d = getDesign("homepage", { cache: "auto", maxAgeMs: 250 });
292
+ ```
293
+
294
+ Use `clearKdfCache()` for explicit invalidation in custom tooling.
295
+
296
+ ## CSS Custom Properties
297
+
298
+ For values not expressible as reusable classes:
299
+
300
+ ```json
301
+ {
302
+ "hero": {
303
+ "title": {
304
+ "className": "text-3xl",
305
+ "css": { "--kdf-accent": "oklch(0.546 0.245 262)" }
306
+ }
307
+ }
308
+ }
309
+ ```
310
+
311
+ Generated CSS can live in `konde.css`. The plugin exposes its path via env
312
+ (`KDF_CLIENT_CSS`); wire the `<link>`/import in your app (e.g. last in
313
+ `globals.css`) — the plugin does not inject it for you.
314
+
315
+ ## Commands
316
+
317
+ - `kdf init` - scaffold the starter `kdf/` folder and generated CSS files.
318
+ - `bun example/preview.ts [tailwind|shadcn|bootstrap|pure-css]` - run the local
319
+ KDF example preview. Use `PORT=4410` to avoid port conflicts and
320
+ `KDF_PREVIEW_OPEN=0` for test/CI runs without opening a browser.
321
+
322
+ ## Next.js Config
323
+
324
+ Default KDF directory (`./kdf`):
325
+
326
+ ```ts
327
+ // next.config.ts
328
+ import withKDF from "@kondeio/kdf/plugin";
329
+
330
+ export default withKDF()(nextConfig);
331
+ ```
332
+
333
+ Custom KDF directory (`./my-design`):
334
+
335
+ ```ts
336
+ // next.config.ts
337
+ import withKDF from "@kondeio/kdf/plugin";
338
+
339
+ export default withKDF({ dir: "./my-design" })(nextConfig);
340
+ ```
341
+
342
+ ## Key Symbols
343
+
344
+ | Symbol | Purpose | Example |
345
+ | --- | --- | --- |
346
+ | `$` | Component binding | `"$": "Button"` |
347
+ | `@` | Shared style reference | `"@button.cta"` |
348
+ | `$layout` | Page section order | `["hero", "footer"]` |
349
+
350
+ ## Documentation and Skills
351
+
352
+ - [`docs/kdf-doc.md`](./docs/kdf-doc.md) - KDF concept, architecture, conventions, and operating model.
353
+ - [`docs/kdf-skill.md`](./docs/kdf-skill.md) - agent-facing implementation and review checklist.
354
+
355
+ ## Contributing
356
+
357
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for local setup, build/test commands,
358
+ and PR conventions. Keep the core UI-library agnostic and the resolver
359
+ server-only.
360
+
361
+ ## Security
362
+
363
+ `@kondeio/kdf` runs a `postinstall` script that scaffolds a starter `kdf/`
364
+ folder into your project (never overwrites, no network calls). To skip it:
365
+ `npm install @kondeio/kdf --ignore-scripts` or `KDF_SKIP_INIT=1`. Full details
366
+ and vulnerability reporting in [SECURITY.md](./SECURITY.md).
367
+
368
+ ## Changelog
369
+
370
+ See [CHANGELOG.md](./CHANGELOG.md).
371
+
372
+ ## License
373
+
374
+ MIT. See [`LICENSE`](./LICENSE) for the full license text.
package/SECURITY.md ADDED
@@ -0,0 +1,53 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ Please report security issues **privately** — do not open a public GitHub issue.
6
+
7
+ Email: **security@konde.io** (or open a private security advisory on the
8
+ GitHub repository).
9
+
10
+ Include a description, affected version, and a minimal reproduction if possible.
11
+ We aim to acknowledge reports within a few business days.
12
+
13
+ ## Install-time behavior (`postinstall`)
14
+
15
+ KDF runs a `postinstall` script that **scaffolds a starter `kdf/` folder** into
16
+ the consuming project so the package works out of the box. You should know
17
+ exactly what it does:
18
+
19
+ - **What it writes:** a `kdf/` folder at the project root (`INIT_CWD`) containing
20
+ starter design JSON (`shared/*.json`, `homepage.json`) and generated CSS files
21
+ (`konde-server.css`, `konde.css`).
22
+ - **What it never does:** it never overwrites an existing `kdf/` folder, never
23
+ touches files outside `kdf/`, makes no network calls, and reads/writes no
24
+ secrets or credentials.
25
+ - **When it is skipped:** it does nothing if `kdf/` already exists.
26
+
27
+ ### Opting out
28
+
29
+ ```bash
30
+ # Skip all install scripts (npm):
31
+ npm install @kondeio/kdf --ignore-scripts
32
+
33
+ # Or disable just KDF scaffolding:
34
+ KDF_SKIP_INIT=1 npm install @kondeio/kdf
35
+ ```
36
+
37
+ You can scaffold manually later with:
38
+
39
+ ```bash
40
+ npx kdf init
41
+ ```
42
+
43
+ ## Reference resolution safety
44
+
45
+ `@ref` component names (e.g. `@button.cta` → `shared/button.json`) are validated
46
+ against `^[A-Za-z0-9_-]+$`. References containing path separators or `..` are
47
+ rejected, so a ref cannot read files outside the `shared/` folder. Design JSON is
48
+ authored by developers (trusted input); this is defense-in-depth.
49
+
50
+ ## Supported versions
51
+
52
+ KDF is pre-1.0 (`0.x`). Security fixes target the latest published `0.x`
53
+ release.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ import { mkdirSync, existsSync, copyFileSync, readdirSync } from "fs";
3
+ import { join, dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { writeKondeCSS } from "./css-generator.js";
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const TEMPLATES_DIR = join(__dirname, "..", "kdf");
8
+ const commands = {
9
+ init: cmdInit,
10
+ };
11
+ function cmdInit() {
12
+ const targetDir = join(process.cwd(), process.env.KDF_DIR || "kdf");
13
+ if (existsSync(targetDir)) {
14
+ console.log("kdf/ directory already exists. Skipping init.");
15
+ return;
16
+ }
17
+ // Create kdf/ and kdf/shared/
18
+ mkdirSync(join(targetDir, "shared"), { recursive: true });
19
+ // Copy shared token files
20
+ const sharedDir = join(TEMPLATES_DIR, "shared");
21
+ if (existsSync(sharedDir)) {
22
+ for (const file of readdirSync(sharedDir).filter((f) => f.endsWith(".json"))) {
23
+ copyFileSync(join(sharedDir, file), join(targetDir, "shared", file));
24
+ }
25
+ }
26
+ // Copy homepage.json as starter
27
+ const homepageSrc = join(TEMPLATES_DIR, "homepage.json");
28
+ if (existsSync(homepageSrc)) {
29
+ copyFileSync(homepageSrc, join(targetDir, "homepage.json"));
30
+ }
31
+ // Generate empty CSS files inside kdf/ folder
32
+ writeKondeCSS(targetDir);
33
+ console.log("Initialized:");
34
+ console.log("");
35
+ console.log(" kdf/");
36
+ console.log(" shared/");
37
+ console.log(" button.json");
38
+ console.log(" card.json");
39
+ console.log(" color.json");
40
+ console.log(" layout.json");
41
+ console.log(" typography.json");
42
+ console.log(" homepage.json");
43
+ console.log(" konde-server.css (critical overrides — import in layout.tsx)");
44
+ console.log(" konde.css (non-critical overrides — <link> last in <head>)");
45
+ }
46
+ // --- Main ---
47
+ const command = process.argv[2];
48
+ if (!command || !commands[command]) {
49
+ console.log("@kondeio/kdf - Design-as-JSON for agent-assisted UI");
50
+ console.log("");
51
+ console.log("Commands:");
52
+ console.log(" init Scaffold kdf/ folder + konde.css");
53
+ console.log("");
54
+ console.log("Usage:");
55
+ console.log(" npx @kondeio/kdf init");
56
+ process.exit(command ? 1 : 0);
57
+ }
58
+ commands[command]();
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Generate empty konde-server.css scaffold.
3
+ * Server-side loaded (import in layout.tsx) — inlined in HTML, no FOUC.
4
+ * For critical overrides that must be present on first paint.
5
+ */
6
+ export declare function generateKondeServerCSS(): string;
7
+ /**
8
+ * Generate empty konde.css scaffold.
9
+ * Client-side loaded (<link> last in <head>) — highest specificity.
10
+ * For non-critical overrides, experiments, CSS hacks.
11
+ */
12
+ export declare function generateKondeCSS(): string;
13
+ /**
14
+ * Write CSS files to disk — only if file doesn't exist.
15
+ * Safe to call multiple times; never overwrites user edits.
16
+ */
17
+ export declare function writeKondeCSS(outputDir?: string): void;
@@ -0,0 +1,59 @@
1
+ import { writeFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ /**
4
+ * Generate empty konde-server.css scaffold.
5
+ * Server-side loaded (import in layout.tsx) — inlined in HTML, no FOUC.
6
+ * For critical overrides that must be present on first paint.
7
+ */
8
+ export function generateKondeServerCSS() {
9
+ return `/* konde-server.css — Critical design overrides (server-rendered) */
10
+ /* Imported in layout.tsx — inlined in HTML, no FOUC */
11
+ /* Edit freely — KDF will never overwrite this file */
12
+
13
+ /* Use for:
14
+ - Critical layout fixes that cause visual shift
15
+ - CSS custom properties needed on first paint
16
+ - Override shared component visibility per page
17
+
18
+ Examples:
19
+ :root { --kdf-primary: #4F46E5; }
20
+ [data-kdf="hero.slider"] { display: none; }
21
+ */
22
+ `;
23
+ }
24
+ /**
25
+ * Generate empty konde.css scaffold.
26
+ * Client-side loaded (<link> last in <head>) — highest specificity.
27
+ * For non-critical overrides, experiments, CSS hacks.
28
+ */
29
+ export function generateKondeCSS() {
30
+ return `/* konde.css — Custom design overrides (client-side) */
31
+ /* Loaded LAST in <head> via <link> — highest specificity */
32
+ /* Edit freely — KDF will never overwrite this file */
33
+
34
+ /* Use for:
35
+ - Fine-tune padding/margin/width
36
+ - Non-critical visual tweaks
37
+ - Quick experiments and CSS hacks
38
+
39
+ Examples:
40
+ [data-kdf="hero.title"] { letter-spacing: -0.02em; }
41
+ [data-kdf="hero.wrapper"] { gap: 3rem; }
42
+ */
43
+ `;
44
+ }
45
+ /**
46
+ * Write CSS files to disk — only if file doesn't exist.
47
+ * Safe to call multiple times; never overwrites user edits.
48
+ */
49
+ export function writeKondeCSS(outputDir) {
50
+ const dir = outputDir || process.cwd();
51
+ const serverCss = join(dir, "konde-server.css");
52
+ const clientCss = join(dir, "konde.css");
53
+ if (!existsSync(serverCss)) {
54
+ writeFileSync(serverCss, generateKondeServerCSS(), "utf-8");
55
+ }
56
+ if (!existsSync(clientCss)) {
57
+ writeFileSync(clientCss, generateKondeCSS(), "utf-8");
58
+ }
59
+ }