fractalstyler2 0.0.2 → 0.3.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.
- package/README.md +60 -45
- package/dist/cli.js +54 -11
- package/dist/index.d.ts +32 -1
- package/dist/index.js +73 -4
- package/dist/mcp/export.d.ts +13 -0
- package/dist/mcp/export.js +76 -0
- package/dist/mcp/schemas/compile_fractals.json +20 -0
- package/dist/mcp/schemas/css_to_fractals.json +16 -0
- package/dist/mcp/schemas/generate_component.json +45 -0
- package/dist/mcp/schemas/get_design_tokens.json +23 -0
- package/dist/mcp/schemas/instructions.md +18 -0
- package/dist/mcp/schemas/list_fractals.json +20 -0
- package/dist/mcp/schemas/snap_to_tokens.json +25 -0
- package/dist/mcp/schemas/validate_recipe.json +16 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +837 -0
- package/dist/styles/_00_tokens.sass +177 -0
- package/{templates/_config.sass → dist/styles/_01_config.sass} +11 -5
- package/dist/styles/_02_fonts.sass +13 -0
- package/dist/styles/_03_responsive.sass +31 -0
- package/dist/styles/{_atoms.sass → _04_atoms.sass} +4 -4
- package/{templates/_molecules.sass → dist/styles/_05_molecules.sass} +16 -12
- package/dist/styles/_06_recipes.sass +189 -0
- package/dist/styles/{_base.sass → _07_base.sass} +3 -2
- package/dist/styles/_08_blocks.sass +433 -0
- package/dist/styles/{_utilities.sass → _09_utilities.sass} +96 -16
- package/dist/styles/_10_layouts.sass +373 -0
- package/dist/styles/_11_own.sass +21 -0
- package/dist/styles/_fractals.sass +7 -6
- package/dist/styles/index.sass +14 -16
- package/mcp.json +11 -0
- package/package.json +14 -6
- package/plugin.json +22 -0
- package/skills/fractal-styler/SKILL.md +83 -0
- package/skills/fractal-styler/references/fractals.md +28 -0
- package/skills/fractal-styler/references/tokens.md +36 -0
- package/skills/style-migration/SKILL.md +45 -0
- package/templates/_00_tokens.sass +177 -0
- package/{dist/styles/_config.sass → templates/_01_config.sass} +11 -5
- package/templates/_02_fonts.sass +13 -0
- package/templates/_03_responsive.sass +31 -0
- package/templates/{_atoms.sass → _04_atoms.sass} +4 -4
- package/{dist/styles/_molecules.sass → templates/_05_molecules.sass} +16 -12
- package/templates/_06_recipes.sass +189 -0
- package/templates/{_base.sass → _07_base.sass} +3 -2
- package/templates/_08_blocks.sass +433 -0
- package/templates/{_utilities.sass → _09_utilities.sass} +96 -16
- package/templates/_10_layouts.sass +373 -0
- package/templates/_11_own.sass +21 -0
- package/templates/_fractals.sass +7 -6
- package/templates/index.sass +14 -16
- package/dist/styles/_blocks.sass +0 -88
- package/dist/styles/_layouts.sass +0 -108
- package/dist/styles/_responsive.sass +0 -43
- package/dist/styles/_tokens.sass +0 -127
- package/templates/_blocks.sass +0 -88
- package/templates/_layouts.sass +0 -108
- package/templates/_responsive.sass +0 -43
- package/templates/_tokens.sass +0 -127
package/README.md
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# fractalstyler2
|
|
2
2
|
|
|
3
|
-
A fractal-composition styling system for SvelteKit. **Every style unit is a SASS
|
|
4
|
-
mixin ("a fractal"), and components and layouts are recipes of smaller fractals.**
|
|
3
|
+
A fractal-composition styling system for SvelteKit. **Every style unit is a SASS mixin ("a fractal"), and components and layouts are recipes of smaller fractals.**
|
|
5
4
|
|
|
6
|
-
Use it either as a **shadcn-style scaffolder** (copying editable SASS into your project's `src/lib/styles`) or as a **direct package dependency**.
|
|
5
|
+
Use it either as a **shadcn-style scaffolder** (copying editable SASS directly into your project's `src/lib/styles`) or as a **direct package dependency**.
|
|
7
6
|
|
|
8
7
|
---
|
|
9
8
|
|
|
10
9
|
## Quickstart (shadcn-style Scaffolding)
|
|
11
10
|
|
|
12
|
-
Scaffold the complete, customizable SASS design system directly into your project
|
|
11
|
+
Scaffold the complete, customizable SASS design system directly into your project:
|
|
13
12
|
|
|
14
13
|
```bash
|
|
15
14
|
# Scaffold into src/lib/styles
|
|
@@ -21,22 +20,27 @@ pnpm dlx fractalstyler2 init
|
|
|
21
20
|
|
|
22
21
|
### Next Steps in Your Project
|
|
23
22
|
|
|
24
|
-
**1. Import the stylesheet in your root
|
|
23
|
+
**1. Import the stylesheet once globally in your root `src/routes/+layout.svelte`:**
|
|
25
24
|
```svelte
|
|
26
25
|
<script>
|
|
27
26
|
import '$lib/styles/index.sass';
|
|
28
27
|
</script>
|
|
29
28
|
```
|
|
30
29
|
|
|
31
|
-
**2. Compose your components using the
|
|
30
|
+
**2. Compose your components using the pure mixin barrel:**
|
|
32
31
|
```svelte
|
|
32
|
+
<div class="pricing-card">
|
|
33
|
+
<span class="badge" data-status="released">Pro Plan</span>
|
|
34
|
+
<h3>$29/mo</h3>
|
|
35
|
+
<p>Full access to all fractal components and layouts.</p>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
33
38
|
<style lang="sass">
|
|
34
39
|
@use '$lib/styles/fractals' as *
|
|
35
40
|
|
|
36
41
|
.pricing-card
|
|
37
|
-
+surface(surface,
|
|
38
|
-
+stack(
|
|
39
|
-
text-align: center
|
|
42
|
+
+surface(surface, m, 6, md) // bg + border + radius(6px) + padding + shadow
|
|
43
|
+
+stack(s, start) // flex-column + gap(s) + top-anchored flow
|
|
40
44
|
</style>
|
|
41
45
|
```
|
|
42
46
|
|
|
@@ -47,15 +51,7 @@ pnpm dlx fractalstyler2 init
|
|
|
47
51
|
If you prefer importing from `node_modules` instead of scaffolding local files:
|
|
48
52
|
|
|
49
53
|
```bash
|
|
50
|
-
npm install fractalstyler2
|
|
51
|
-
# or
|
|
52
54
|
pnpm add fractalstyler2
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Your app also needs `sass`:
|
|
56
|
-
```bash
|
|
57
|
-
npm install -D sass
|
|
58
|
-
# or
|
|
59
55
|
pnpm add -D sass
|
|
60
56
|
```
|
|
61
57
|
|
|
@@ -70,37 +66,54 @@ pnpm add -D sass
|
|
|
70
66
|
@use 'fractalstyler2/fractals' as *
|
|
71
67
|
|
|
72
68
|
.card
|
|
73
|
-
+surface(surface, s,
|
|
69
|
+
+surface(surface, s, 6)
|
|
74
70
|
+stack(s)
|
|
75
71
|
</style>
|
|
76
72
|
```
|
|
77
73
|
|
|
78
74
|
---
|
|
79
75
|
|
|
80
|
-
## The
|
|
76
|
+
## The Physical Scale Hierarchy
|
|
77
|
+
|
|
78
|
+
The design system files in `src/lib/styles/` are numbered sequentially from indivisible math to page layouts:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
index.sass ──► Master Entrypoint (Forwards fractals + loads CSS cascade)
|
|
82
|
+
_fractals.sass ──► Pure Mixin Barrel (Emits 0 bytes CSS)
|
|
83
|
+
|
|
84
|
+
── Phase 1: Pure Functions & Math (Zero CSS Emitted) ─────────────────────────
|
|
85
|
+
_00_tokens.sass ──► Raw CSS custom properties on :root & theme modes
|
|
86
|
+
_01_config.sass ──► Scales, maps, resolvers (space, radius, surface, ink)
|
|
87
|
+
_02_fonts.sass ──► Local @font-face declarations
|
|
88
|
+
_03_responsive.sass ──► Breakpoint helpers (+at, +below, +between)
|
|
89
|
+
_04_atoms.sass ──► Single-decision primitives (+box, +row, +bg, +ink, +pad, +gap)
|
|
90
|
+
_05_molecules.sass ──► Compositions of atoms (+stack, +cluster, +surface, +cols)
|
|
91
|
+
_06_recipes.sass ──► Macro component archetypes (=control, =select, =card, =partition)
|
|
92
|
+
|
|
93
|
+
── Phase 2: CSS Cascade Emitters (Loaded once globally by index.sass) ─────────
|
|
94
|
+
_07_base.sass ──► Global HTML element resets
|
|
95
|
+
_08_blocks.sass ──► Semantic component classes (.surface, .panel, .select, .badge)
|
|
96
|
+
_09_utilities.sass ──► 1:1 atomic markup projections (.pad-*, .pad-top-*, .gap-*, .hide-desktop)
|
|
97
|
+
_10_layouts.sass ──► Page layout templates (.docs, .card-grid, .hero, .holy-grail)
|
|
98
|
+
_11_own.sass ──► Bespoke local project overrides
|
|
99
|
+
```
|
|
81
100
|
|
|
82
|
-
|
|
83
|
-
fractals. They form four self-similar tiers — each tier is "a recipe of the one
|
|
84
|
-
below":
|
|
101
|
+
---
|
|
85
102
|
|
|
86
|
-
|
|
87
|
-
| --- | --- | --- |
|
|
88
|
-
| **Config** | scales-as-data + resolvers | `space()`, `radius()`, `align()`, `$breakpoints` |
|
|
89
|
-
| **Atoms** | one decision each | `+box` `+row` `+gap` `+pad` `+border` `+radius` `+bg` `+ink` `+type` `+sticky` |
|
|
90
|
-
| **Molecules** | graphs of atoms | `+stack` `+cluster` `+cover` `+frame` `+surface` `+cols` `+auto-grid` |
|
|
91
|
-
| **Components / Layouts** | graphs of molecules | `.card` `.button` · `.grid-3` `.hero` `.holy-grail` `.docs` `.app-shell` |
|
|
103
|
+
## The Strict 21-Token Contract
|
|
92
104
|
|
|
93
|
-
|
|
105
|
+
All themes and surface colors resolve from the 21 variables defined in `_00_tokens.sass`:
|
|
94
106
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
- **Surfaces**: `--bg`, `--bg-surface`, `--bg-raised`, `--bg-panel`, `--bg-footer`, `--bg-popover`, `--bg-dialog`, `--bg-terminal`, `--bg-input`, `--bg-canvas`
|
|
108
|
+
- **Text & Ink**: `--text-primary`, `--text-secondary`, `--text-muted`, `--text-inverse`
|
|
109
|
+
- **States & Feedback**: `--state-hover`, `--state-hover-subtle`, `--state-selected`
|
|
110
|
+
- **Borders & Accents**: `--border`, `--border-subtle`, `--theme-color`, `--theme-color-alt` *(aliased to `--theme`)*
|
|
98
111
|
|
|
99
112
|
---
|
|
100
113
|
|
|
101
114
|
## Color Mode
|
|
102
115
|
|
|
103
|
-
Light is the marker-free default (SSR-safe). Dark
|
|
116
|
+
Light is the marker-free default (SSR-safe). Dark mode is activated via `prefers-color-scheme: dark` or explicitly via `data-mode="dark"` on `<html>`:
|
|
104
117
|
|
|
105
118
|
```js
|
|
106
119
|
import { toggleMode, setMode } from 'fractalstyler2';
|
|
@@ -110,18 +123,20 @@ setMode('dark'); // force mode
|
|
|
110
123
|
|
|
111
124
|
---
|
|
112
125
|
|
|
113
|
-
##
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
## Documentation Index
|
|
127
|
+
|
|
128
|
+
| Guide | Description |
|
|
129
|
+
|---|---|
|
|
130
|
+
| [01. Philosophy](docs/01-philosophy.md) | The fractal model, self-similarity, and dual consumption |
|
|
131
|
+
| [02. Structure](docs/02-structure.md) | File anatomy, the 12-file numbered scale, and cascade order |
|
|
132
|
+
| [03. Getting Started](docs/03-getting-started.md) | Scaffolding, imports, and wiring into SvelteKit |
|
|
133
|
+
| [04. Fractals Reference](docs/04-fractals-reference.md) | Comprehensive reference for every atom and molecule mixin |
|
|
134
|
+
| [05. Tokens & Theming](docs/05-tokens-and-theming.md) | Fluid scales, the 21-variable contract, and dark mode |
|
|
135
|
+
| [06. Utilities Reference](docs/06-utilities.md) | Generated atomic classes, directional padding, and visibility |
|
|
136
|
+
| [07. Components & Layouts](docs/07-components-and-layouts.md) | Shipped blocks, cards, and page layout templates |
|
|
137
|
+
| [08. Recipes & Patterns](docs/08-recipes.md) | Worked examples: pricing card, responsive docs shell, dialog |
|
|
138
|
+
| [09. Migration from v1](docs/09-migration-from-v1.md) | Upgrading from older unnumbered stylesheets |
|
|
139
|
+
| [DESIGN.md](DESIGN.md) | Golden UI invariants, card containment laws, and defect prevention |
|
|
125
140
|
|
|
126
141
|
---
|
|
127
142
|
|
package/dist/cli.js
CHANGED
|
@@ -18,22 +18,29 @@ function getTemplatesDir() {
|
|
|
18
18
|
}
|
|
19
19
|
function printUsage() {
|
|
20
20
|
console.log(`
|
|
21
|
-
fractalstyler2 — SASS fractal design system scaffolder
|
|
21
|
+
fractalstyler2 — SASS fractal design system scaffolder & MCP server
|
|
22
22
|
|
|
23
23
|
Usage:
|
|
24
24
|
npx fractalstyler2 init [dest] [options]
|
|
25
|
+
npx fractalstyler2 mcp
|
|
26
|
+
npx fractalstyler2 mcp:install
|
|
27
|
+
npx fractalstyler2 mcp:export [dest]
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
dest
|
|
29
|
+
Commands:
|
|
30
|
+
init [dest] Scaffold SASS partials into target directory (default: src/lib/styles)
|
|
31
|
+
mcp Start the Model Context Protocol (MCP) server for OpenDesign, Claude, etc.
|
|
32
|
+
mcp:install Automatically install MCP schemas & config into Antigravity & OpenCode
|
|
33
|
+
mcp:export [dest] Export static MCP tool schema JSON files to target directory (default: .mcp)
|
|
28
34
|
|
|
29
35
|
Options:
|
|
30
|
-
-f, --force
|
|
31
|
-
-h, --help
|
|
36
|
+
-f, --force Overwrite files if they already exist
|
|
37
|
+
-h, --help Show this help message
|
|
32
38
|
|
|
33
39
|
Examples:
|
|
34
40
|
npx fractalstyler2 init
|
|
35
|
-
npx fractalstyler2
|
|
36
|
-
npx fractalstyler2
|
|
41
|
+
npx fractalstyler2 mcp
|
|
42
|
+
npx fractalstyler2 mcp:install
|
|
43
|
+
npx fractalstyler2 mcp:export ~/.gemini/antigravity/mcp/fractalstyler2
|
|
37
44
|
`);
|
|
38
45
|
}
|
|
39
46
|
function init(destArg, force) {
|
|
@@ -82,7 +89,7 @@ function init(destArg, force) {
|
|
|
82
89
|
@use '${fractalsPath}' as *
|
|
83
90
|
|
|
84
91
|
.card
|
|
85
|
-
+surface(surface, s,
|
|
92
|
+
+surface(surface, s, 6)
|
|
86
93
|
+stack(s)
|
|
87
94
|
</style>
|
|
88
95
|
`);
|
|
@@ -92,12 +99,48 @@ const showHelp = args.includes('-h') || args.includes('--help');
|
|
|
92
99
|
const force = args.includes('-f') || args.includes('--force');
|
|
93
100
|
const positional = args.filter((a) => !a.startsWith('-'));
|
|
94
101
|
const command = positional[0];
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
const VALID_COMMANDS = ['init', 'mcp', 'mcp:export', 'mcp:install'];
|
|
103
|
+
if (showHelp || (command && !VALID_COMMANDS.includes(command))) {
|
|
104
|
+
if (command && !VALID_COMMANDS.includes(command)) {
|
|
97
105
|
console.error(`Unknown command: ${command}`);
|
|
98
106
|
}
|
|
99
107
|
printUsage();
|
|
100
|
-
process.exit(command && command
|
|
108
|
+
process.exit(command && !VALID_COMMANDS.includes(command) ? 1 : 0);
|
|
109
|
+
}
|
|
110
|
+
else if (command === 'mcp') {
|
|
111
|
+
import('./mcp/server.js');
|
|
112
|
+
}
|
|
113
|
+
else if (command === 'mcp:export') {
|
|
114
|
+
import('./mcp/export.js').then(({ exportSchemas }) => {
|
|
115
|
+
const dest = positional[1] || '.mcp/fractalstyler2';
|
|
116
|
+
const { created, dir } = exportSchemas(dest);
|
|
117
|
+
console.log(`\n▲ Exported ${created} MCP schema files to: ${dir}\n`);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else if (command === 'mcp:install') {
|
|
121
|
+
import('./mcp/export.js').then(({ installToAntigravity, installToOpenCode }) => {
|
|
122
|
+
console.log(`\n▲ Installing fractalstyler2 MCP schemas & configuration...\n`);
|
|
123
|
+
try {
|
|
124
|
+
const agy = installToAntigravity();
|
|
125
|
+
console.log(` \x1b[32m✔\x1b[0m Antigravity MCP schemas: ${agy.dir}`);
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.log(` \x1b[90m-\x1b[0m Antigravity install skipped (${e.message})`);
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const oc = installToOpenCode();
|
|
132
|
+
if (oc.success) {
|
|
133
|
+
console.log(` \x1b[32m✔\x1b[0m OpenCode MCP configured: ${oc.configPath}`);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
console.log(` \x1b[90m-\x1b[0m OpenCode config not found (skipped)`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
console.log(` \x1b[90m-\x1b[0m OpenCode install skipped (${e.message})`);
|
|
141
|
+
}
|
|
142
|
+
console.log(`\nDone! fractalstyler2 MCP is ready.\n`);
|
|
143
|
+
});
|
|
101
144
|
}
|
|
102
145
|
else if (command === 'init') {
|
|
103
146
|
init(positional[1], force);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
export declare const version = "0.0
|
|
1
|
+
export declare const version = "0.3.0";
|
|
2
2
|
export type Mode = 'light' | 'dark';
|
|
3
3
|
/** Set the color mode by writing the [data-mode] marker on <html>. */
|
|
4
4
|
export declare function setMode(mode: Mode): void;
|
|
5
5
|
/** Toggle between light and dark, returning the new mode. */
|
|
6
6
|
export declare function toggleMode(): Mode;
|
|
7
|
+
export declare const breakpoints: {
|
|
8
|
+
readonly sm: "640px";
|
|
9
|
+
readonly md: "768px";
|
|
10
|
+
readonly lg: "1024px";
|
|
11
|
+
readonly xl: "1240px";
|
|
12
|
+
};
|
|
13
|
+
export declare const spaceScale: readonly ["3xs", "2xs", "xs", "s", "m", "l", "xl", "2xl", "3xl", "s-l"];
|
|
14
|
+
export declare const typographyScale: readonly ["xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl"];
|
|
15
|
+
export declare const radiusSteps: readonly ["0", "2", "3", "4", "6", "8", "12", "16", "24", "full"];
|
|
16
|
+
export declare const surfaceRoles: readonly ["bg", "surface", "raised", "panel", "footer", "popover", "dialog", "terminal", "input", "canvas"];
|
|
17
|
+
export declare const inkRoles: readonly ["primary", "secondary", "muted", "inverse", "theme-color", "theme-color-alt"];
|
|
18
|
+
export declare const tokens: {
|
|
19
|
+
readonly version: "0.3.0";
|
|
20
|
+
readonly breakpoints: {
|
|
21
|
+
readonly sm: "640px";
|
|
22
|
+
readonly md: "768px";
|
|
23
|
+
readonly lg: "1024px";
|
|
24
|
+
readonly xl: "1240px";
|
|
25
|
+
};
|
|
26
|
+
readonly spaceScale: readonly ["3xs", "2xs", "xs", "s", "m", "l", "xl", "2xl", "3xl", "s-l"];
|
|
27
|
+
readonly typographyScale: readonly ["xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl"];
|
|
28
|
+
readonly radiusSteps: readonly ["0", "2", "3", "4", "6", "8", "12", "16", "24", "full"];
|
|
29
|
+
readonly surfaceRoles: readonly ["bg", "surface", "raised", "panel", "footer", "popover", "dialog", "terminal", "input", "canvas"];
|
|
30
|
+
readonly inkRoles: readonly ["primary", "secondary", "muted", "inverse", "theme-color", "theme-color-alt"];
|
|
31
|
+
};
|
|
32
|
+
export type Breakpoint = keyof typeof breakpoints;
|
|
33
|
+
export type SpaceStep = (typeof spaceScale)[number];
|
|
34
|
+
export type TypographyStep = (typeof typographyScale)[number];
|
|
35
|
+
export type RadiusStep = (typeof radiusSteps)[number];
|
|
36
|
+
export type SurfaceRole = (typeof surfaceRoles)[number];
|
|
37
|
+
export type InkRole = (typeof inkRoles)[number];
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// fractalstyler2 — a fractal-composition styling system for SvelteKit.
|
|
2
2
|
//
|
|
3
|
-
// The product is the SASS in ./fractals and ./
|
|
3
|
+
// The product is the SASS in ./fractals and ./styles, surfaced as:
|
|
4
4
|
// import 'fractalstyler2/styles' // emit the full stylesheet
|
|
5
5
|
// @use 'fractalstyler2/fractals' as * // compose your own with the mixins
|
|
6
6
|
//
|
|
7
|
-
// This entry ships
|
|
8
|
-
|
|
9
|
-
export const version = '0.0.1';
|
|
7
|
+
// This entry ships runtime helpers and token metadata.
|
|
8
|
+
export const version = '0.3.0';
|
|
10
9
|
/** Set the color mode by writing the [data-mode] marker on <html>. */
|
|
11
10
|
export function setMode(mode) {
|
|
12
11
|
if (typeof document === 'undefined')
|
|
@@ -20,3 +19,73 @@ export function toggleMode() {
|
|
|
20
19
|
setMode(next);
|
|
21
20
|
return next;
|
|
22
21
|
}
|
|
22
|
+
// Design Token Metadata
|
|
23
|
+
export const breakpoints = {
|
|
24
|
+
sm: '640px',
|
|
25
|
+
md: '768px',
|
|
26
|
+
lg: '1024px',
|
|
27
|
+
xl: '1240px'
|
|
28
|
+
};
|
|
29
|
+
export const spaceScale = [
|
|
30
|
+
'3xs',
|
|
31
|
+
'2xs',
|
|
32
|
+
'xs',
|
|
33
|
+
's',
|
|
34
|
+
'm',
|
|
35
|
+
'l',
|
|
36
|
+
'xl',
|
|
37
|
+
'2xl',
|
|
38
|
+
'3xl',
|
|
39
|
+
's-l'
|
|
40
|
+
];
|
|
41
|
+
export const typographyScale = [
|
|
42
|
+
'xs',
|
|
43
|
+
'sm',
|
|
44
|
+
'md',
|
|
45
|
+
'lg',
|
|
46
|
+
'xl',
|
|
47
|
+
'2xl',
|
|
48
|
+
'3xl',
|
|
49
|
+
'4xl'
|
|
50
|
+
];
|
|
51
|
+
export const radiusSteps = [
|
|
52
|
+
'0',
|
|
53
|
+
'2',
|
|
54
|
+
'3',
|
|
55
|
+
'4',
|
|
56
|
+
'6',
|
|
57
|
+
'8',
|
|
58
|
+
'12',
|
|
59
|
+
'16',
|
|
60
|
+
'24',
|
|
61
|
+
'full'
|
|
62
|
+
];
|
|
63
|
+
export const surfaceRoles = [
|
|
64
|
+
'bg',
|
|
65
|
+
'surface',
|
|
66
|
+
'raised',
|
|
67
|
+
'panel',
|
|
68
|
+
'footer',
|
|
69
|
+
'popover',
|
|
70
|
+
'dialog',
|
|
71
|
+
'terminal',
|
|
72
|
+
'input',
|
|
73
|
+
'canvas'
|
|
74
|
+
];
|
|
75
|
+
export const inkRoles = [
|
|
76
|
+
'primary',
|
|
77
|
+
'secondary',
|
|
78
|
+
'muted',
|
|
79
|
+
'inverse',
|
|
80
|
+
'theme-color',
|
|
81
|
+
'theme-color-alt'
|
|
82
|
+
];
|
|
83
|
+
export const tokens = {
|
|
84
|
+
version,
|
|
85
|
+
breakpoints,
|
|
86
|
+
spaceScale,
|
|
87
|
+
typographyScale,
|
|
88
|
+
radiusSteps,
|
|
89
|
+
surfaceRoles,
|
|
90
|
+
inkRoles
|
|
91
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function getSchemasDir(): string;
|
|
2
|
+
export declare function exportSchemas(targetDir: string): {
|
|
3
|
+
created: number;
|
|
4
|
+
dir: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function installToAntigravity(): {
|
|
7
|
+
success: boolean;
|
|
8
|
+
dir: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function installToOpenCode(): {
|
|
11
|
+
success: boolean;
|
|
12
|
+
configPath: string;
|
|
13
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, copyFileSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
export function getSchemasDir() {
|
|
6
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const candidates = [
|
|
8
|
+
join(HERE, 'schemas'),
|
|
9
|
+
join(HERE, '..', 'mcp', 'schemas'),
|
|
10
|
+
join(HERE, '..', '..', 'src', 'lib', 'mcp', 'schemas'),
|
|
11
|
+
join(process.cwd(), 'src', 'lib', 'mcp', 'schemas'),
|
|
12
|
+
join(process.cwd(), 'dist', 'mcp', 'schemas')
|
|
13
|
+
];
|
|
14
|
+
for (const candidate of candidates) {
|
|
15
|
+
if (existsSync(candidate))
|
|
16
|
+
return candidate;
|
|
17
|
+
}
|
|
18
|
+
throw new Error(`Schemas directory not found. Searched: ${candidates.join(', ')}`);
|
|
19
|
+
}
|
|
20
|
+
export function exportSchemas(targetDir) {
|
|
21
|
+
const resolvedTarget = resolve(process.cwd(), targetDir);
|
|
22
|
+
mkdirSync(resolvedTarget, { recursive: true });
|
|
23
|
+
const schemasDir = getSchemasDir();
|
|
24
|
+
const files = readdirSync(schemasDir);
|
|
25
|
+
let created = 0;
|
|
26
|
+
for (const file of files) {
|
|
27
|
+
const srcFile = join(schemasDir, file);
|
|
28
|
+
const destFile = join(resolvedTarget, file);
|
|
29
|
+
copyFileSync(srcFile, destFile);
|
|
30
|
+
created++;
|
|
31
|
+
}
|
|
32
|
+
return { created, dir: resolvedTarget };
|
|
33
|
+
}
|
|
34
|
+
export function installToAntigravity() {
|
|
35
|
+
const home = os.homedir();
|
|
36
|
+
const agyMcpDir = join(home, '.gemini', 'antigravity', 'mcp', 'fractalstyler2');
|
|
37
|
+
const agyConfigPath = join(home, '.gemini', 'antigravity', 'mcp_config.json');
|
|
38
|
+
exportSchemas(agyMcpDir);
|
|
39
|
+
// Update mcp_config.json if it exists or create it
|
|
40
|
+
let config = { mcpServers: {} };
|
|
41
|
+
if (existsSync(agyConfigPath)) {
|
|
42
|
+
try {
|
|
43
|
+
config = JSON.parse(readFileSync(agyConfigPath, 'utf8'));
|
|
44
|
+
}
|
|
45
|
+
catch { }
|
|
46
|
+
}
|
|
47
|
+
if (!config.mcpServers)
|
|
48
|
+
config.mcpServers = {};
|
|
49
|
+
config.mcpServers.fractalstyler2 = {
|
|
50
|
+
command: 'node',
|
|
51
|
+
args: [join(dirname(fileURLToPath(import.meta.url)), 'server.js')],
|
|
52
|
+
env: {}
|
|
53
|
+
};
|
|
54
|
+
writeFileSync(agyConfigPath, JSON.stringify(config, null, 2), 'utf8');
|
|
55
|
+
return { success: true, dir: agyMcpDir };
|
|
56
|
+
}
|
|
57
|
+
export function installToOpenCode() {
|
|
58
|
+
const home = os.homedir();
|
|
59
|
+
const ocConfigPath = join(home, '.config', 'opencode', 'opencode.json');
|
|
60
|
+
if (existsSync(ocConfigPath)) {
|
|
61
|
+
try {
|
|
62
|
+
const config = JSON.parse(readFileSync(ocConfigPath, 'utf8'));
|
|
63
|
+
if (!config.mcp)
|
|
64
|
+
config.mcp = {};
|
|
65
|
+
config.mcp.fractalstyler2 = {
|
|
66
|
+
type: 'local',
|
|
67
|
+
command: ['node', join(dirname(fileURLToPath(import.meta.url)), 'server.js')],
|
|
68
|
+
enabled: true
|
|
69
|
+
};
|
|
70
|
+
writeFileSync(ocConfigPath, JSON.stringify(config, null, 2), 'utf8');
|
|
71
|
+
return { success: true, configPath: ocConfigPath };
|
|
72
|
+
}
|
|
73
|
+
catch { }
|
|
74
|
+
}
|
|
75
|
+
return { success: false, configPath: ocConfigPath };
|
|
76
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "compile_fractals",
|
|
3
|
+
"description": "Compiles indented SASS fractal mixins into CSS. Useful for live preview in OpenDesign, web apps, or verifying style output.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"sassCode": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Indented SASS code. Can use any fractal mixin (+surface, +stack, +gap, etc.)."
|
|
10
|
+
},
|
|
11
|
+
"className": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Optional CSS class name to wrap the mixins under (e.g. 'preview-card'). Defaults to 'element'."
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"required": [
|
|
17
|
+
"sassCode"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "css_to_fractals",
|
|
3
|
+
"description": "Converts raw CSS declarations (from Figma/OpenDesign inspection) into idiomatic fractalstyler2 SASS mixin recipes (+surface, +stack, +cluster, etc.).",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"css": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Raw CSS block or declaration lines"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"required": [
|
|
13
|
+
"css"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "generate_component",
|
|
3
|
+
"description": "Generates a production-ready Svelte 5 component with runes and scoped SASS fractal mixins.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Component name (e.g. PricingCard, UserAvatar, HeroBanner)"
|
|
10
|
+
},
|
|
11
|
+
"type": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"enum": [
|
|
14
|
+
"card",
|
|
15
|
+
"panel",
|
|
16
|
+
"button",
|
|
17
|
+
"badge",
|
|
18
|
+
"modal",
|
|
19
|
+
"hero",
|
|
20
|
+
"nav",
|
|
21
|
+
"custom"
|
|
22
|
+
],
|
|
23
|
+
"description": "Type of component recipe."
|
|
24
|
+
},
|
|
25
|
+
"elevation": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": [
|
|
28
|
+
"none",
|
|
29
|
+
"sm",
|
|
30
|
+
"md",
|
|
31
|
+
"lg"
|
|
32
|
+
],
|
|
33
|
+
"description": "Surface elevation."
|
|
34
|
+
},
|
|
35
|
+
"description": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Detailed description of component purpose and props."
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"required": [
|
|
41
|
+
"name",
|
|
42
|
+
"type"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "get_design_tokens",
|
|
3
|
+
"description": "Returns the complete structured JSON design tokens (fluid Utopia space scales, typography, radii, shadows, surfaces, ink colors, breakpoints).",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"category": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"enum": [
|
|
10
|
+
"all",
|
|
11
|
+
"space",
|
|
12
|
+
"typography",
|
|
13
|
+
"radius",
|
|
14
|
+
"shadows",
|
|
15
|
+
"surfaces",
|
|
16
|
+
"ink",
|
|
17
|
+
"breakpoints"
|
|
18
|
+
],
|
|
19
|
+
"description": "Optional category filter (all, space, typography, radius, shadows, surfaces, ink, breakpoints). Defaults to 'all'."
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# fractalstyler2 MCP Server
|
|
2
|
+
|
|
3
|
+
The fractalstyler2 MCP server provides tools to inspect design tokens, snap canvas pixel values to Utopia tokens, compile indented SASS fractal mixins to live CSS, generate Svelte 5 runes components with scoped SASS, and lint style recipes.
|
|
4
|
+
|
|
5
|
+
## Available Tools:
|
|
6
|
+
1. **compile_fractals**: Compiles indented SASS fractal mixins (+surface, +stack, +gap, etc.) into live CSS.
|
|
7
|
+
2. **get_design_tokens**: Returns structured JSON for fluid space scale (3xs..3xl), typography, radii, shadows, surfaces, and ink roles.
|
|
8
|
+
3. **snap_to_tokens**: Snaps raw pixel measurements (gap, padding, radius, fontSize) from canvas/inspection to the closest design tokens.
|
|
9
|
+
4. **css_to_fractals**: Converts raw CSS declarations into idiomatic fractal mixin recipes.
|
|
10
|
+
5. **generate_component**: Generates complete Svelte 5 components with runes and scoped SASS fractals.
|
|
11
|
+
6. **validate_recipe**: Lints code against golden rules (flags legacy v1 classes like gap8/pad16, hardcoded pixels, modifier classes).
|
|
12
|
+
7. **list_fractals**: Catalogs all atom & molecule mixins with signatures.
|
|
13
|
+
|
|
14
|
+
## Golden Rules:
|
|
15
|
+
- Never hardcode values that tokens cover; use `+gap(m)`, `+radius(6)`, `+bg(surface)`.
|
|
16
|
+
- Compose fractals (`+surface`, `+stack`, `+cluster`); write raw CSS only for unique lines.
|
|
17
|
+
- Express component state on `data-*` / `aria-*` attributes, never modifier classes.
|
|
18
|
+
- No legacy v1 classes (e.g. `gap8`, `pad16`, `w100`, `.stack` in markup).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "list_fractals",
|
|
3
|
+
"description": "Returns the catalog of all available atom & molecule mixins and layout templates with their signatures and descriptions.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"tier": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"enum": [
|
|
10
|
+
"all",
|
|
11
|
+
"atoms",
|
|
12
|
+
"molecules",
|
|
13
|
+
"recipes",
|
|
14
|
+
"layouts"
|
|
15
|
+
],
|
|
16
|
+
"description": "Filter by fractal tier (all, atoms, molecules, recipes, layouts)."
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "snap_to_tokens",
|
|
3
|
+
"description": "Takes raw pixel values (e.g. from canvas elements in OpenDesign / Figma) and snaps them to the nearest fractalstyler2 design tokens, CSS variables, and suggested mixins.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"gap": {
|
|
8
|
+
"type": "number",
|
|
9
|
+
"description": "Gap in pixels (e.g. 16)"
|
|
10
|
+
},
|
|
11
|
+
"padding": {
|
|
12
|
+
"type": "number",
|
|
13
|
+
"description": "Padding in pixels (e.g. 24)"
|
|
14
|
+
},
|
|
15
|
+
"radius": {
|
|
16
|
+
"type": "number",
|
|
17
|
+
"description": "Border radius in pixels (e.g. 10)"
|
|
18
|
+
},
|
|
19
|
+
"fontSize": {
|
|
20
|
+
"type": "number",
|
|
21
|
+
"description": "Font size in pixels (e.g. 18)"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|