@symbo.ls/mcp 1.0.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 (35) hide show
  1. package/.env.example +16 -0
  2. package/.env.railway +13 -0
  3. package/LICENSE +21 -0
  4. package/README.md +184 -0
  5. package/mcp.json +57 -0
  6. package/package.json +20 -0
  7. package/pyproject.toml +25 -0
  8. package/railway.toml +26 -0
  9. package/run.sh +17 -0
  10. package/symbols_mcp/__init__.py +1 -0
  11. package/symbols_mcp/server.py +1114 -0
  12. package/symbols_mcp/skills/ACCESSIBILITY.md +471 -0
  13. package/symbols_mcp/skills/ACCESSIBILITY_AUDITORY.md +70 -0
  14. package/symbols_mcp/skills/AGENT_INSTRUCTIONS.md +257 -0
  15. package/symbols_mcp/skills/BRAND_INDENTITY.md +69 -0
  16. package/symbols_mcp/skills/BUILT_IN_COMPONENTS.md +304 -0
  17. package/symbols_mcp/skills/CLAUDE.md +2158 -0
  18. package/symbols_mcp/skills/CLI_QUICK_START.md +205 -0
  19. package/symbols_mcp/skills/DESIGN_CRITIQUE.md +64 -0
  20. package/symbols_mcp/skills/DESIGN_DIRECTION.md +320 -0
  21. package/symbols_mcp/skills/DESIGN_SYSTEM_ARCHITECT.md +64 -0
  22. package/symbols_mcp/skills/DESIGN_SYSTEM_CONFIG.md +487 -0
  23. package/symbols_mcp/skills/DESIGN_SYSTEM_IN_PROPS.md +136 -0
  24. package/symbols_mcp/skills/DESIGN_TO_CODE.md +64 -0
  25. package/symbols_mcp/skills/DESIGN_TREND.md +50 -0
  26. package/symbols_mcp/skills/DOMQL_v2-v3_MIGRATION.md +236 -0
  27. package/symbols_mcp/skills/FIGMA_MATCHING.md +63 -0
  28. package/symbols_mcp/skills/GARY_TAN.md +80 -0
  29. package/symbols_mcp/skills/MARKETING_ASSETS.md +66 -0
  30. package/symbols_mcp/skills/MIGRATE_TO_SYMBOLS.md +614 -0
  31. package/symbols_mcp/skills/QUICKSTART.md +79 -0
  32. package/symbols_mcp/skills/SYMBOLS_LOCAL_INSTRUCTIONS.md +1405 -0
  33. package/symbols_mcp/skills/THE_PRESENTATION.md +69 -0
  34. package/symbols_mcp/skills/UI_UX_PATTERNS.md +68 -0
  35. package/windsurf-mcp-config.json +18 -0
@@ -0,0 +1,1405 @@
1
+ # DOMQL/Symbols Project Structure - AI Instructions
2
+
3
+ ## Overview
4
+
5
+ This is a strict, environment-agnostic folder structure designed for the Symbols platform. It generates independent files without JavaScript module preloading, enabling seamless rendering across all environments: VSCode, file structure, Symbols platform, server rendering, and web browsers.
6
+
7
+ ## Core Principle
8
+
9
+ **NO JavaScript imports/exports for component usage.** Components are registered once in their respective folders and reused through a declarative configuration tree using object notation.
10
+
11
+ ---
12
+
13
+ ## Folder Structure & Export Patterns
14
+
15
+ ### 1. **Components** (`/smbls/components/`)
16
+
17
+ **File Pattern:**
18
+
19
+ ```javascript
20
+ // components/Header.js
21
+ export const Header = {
22
+ extends: "Flex", // Base component type
23
+ minWidth: "G2",
24
+ padding: "A",
25
+ // Props and styling applied directly - no 'props' wrapper
26
+
27
+ // Nested children as properties
28
+ Search: {
29
+ extends: "Input",
30
+ flex: 1,
31
+ },
32
+ Avatar: {
33
+ extends: "Image",
34
+ boxSize: "B",
35
+ },
36
+ };
37
+ ```
38
+
39
+ **Key Rules:**
40
+
41
+ - Each component is a named export: `export const ComponentName = { ... }`
42
+ - Component name MUST match filename (PascalCase)
43
+ - Contains declarative object structure with nested child components
44
+ - Can reference other components by name in the tree without imports
45
+ - Props use design system tokens (e.g., `minWidth: 'G2'`, `padding: 'A'`)
46
+
47
+ **Usage in Components Tree:**
48
+
49
+ ```javascript
50
+ {
51
+ Header: {}, // No import needed, referenced by name
52
+ Content: {
53
+ Article: {},
54
+ }
55
+ }
56
+ ```
57
+
58
+ ---
59
+
60
+ ### 2. **Pages** (`/smbls/pages/`)
61
+
62
+ **File Pattern:**
63
+
64
+ ```javascript
65
+ // pages/add-network.js (dash-case filename)
66
+ export const addNetwork = {
67
+ extends: "Page", // camelCase export name
68
+ width: "100%",
69
+ padding: "A",
70
+
71
+ // Event handlers applied directly to properties
72
+ onRender: async (el, state) => {
73
+ await el.call("auth");
74
+ },
75
+
76
+ Form: {
77
+ extends: "Box",
78
+ Input: {
79
+ extends: "Input",
80
+ placeholder: "Network name",
81
+ },
82
+ },
83
+ };
84
+ ```
85
+
86
+ **Key Rules:**
87
+
88
+ - Filenames use dash-case (kebab-case): `add-network.js`, `edit-node.js`, `dashboard.js`
89
+ - Exports use camelCase: `export const addNetwork = { ... }`, `export const editNode = { ... }`
90
+ - Pages extend from 'Page' component
91
+ - Contain complete page structure with nested components
92
+ - Can call functions using `el.call('functionName')`
93
+
94
+ **Usage:**
95
+ Pages are registered in [pages/index.js](smbls/pages/index.js) as a default export object mapping routes to pages.
96
+
97
+ ---
98
+
99
+ ### 3. **Functions** (`/smbls/functions/`)
100
+
101
+ **File Pattern:**
102
+
103
+ ```javascript
104
+ // functions/parseNetworkRow.js
105
+ export const parseNetworkRow = function parseNetworkRow(data) {
106
+ // Function logic
107
+ return processedData;
108
+ };
109
+ ```
110
+
111
+ **Key Rules:**
112
+
113
+ - Each function is a named export matching filename (camelCase)
114
+ - Functions are pure, standalone utilities
115
+ - NO imports of other functions; reuse only through composition
116
+
117
+ **Usage in Components:**
118
+
119
+ ```javascript
120
+ {
121
+ Button: {
122
+ onClick: (el) => el.call("parseNetworkRow", data);
123
+ }
124
+ }
125
+ ```
126
+
127
+ Functions are called via `element.call('functionName', ...args)` from within component handlers.
128
+
129
+ ---
130
+
131
+ ### 4. **Methods** (`/smbls/methods/`)
132
+
133
+ **File Pattern:**
134
+
135
+ ```javascript
136
+ // methods/formatDate.js
137
+ export const formatDate = function (date) {
138
+ return new Intl.DateTimeFormat().format(date);
139
+ };
140
+ ```
141
+
142
+ **Key Rules:**
143
+
144
+ - Utility methods that extend element behavior
145
+ - Registered once, reused across all components
146
+
147
+ **Usage in Components:**
148
+
149
+ ```javascript
150
+ {
151
+ Button: {
152
+ onClick: (el) => el.methodName(args);
153
+ }
154
+ }
155
+ ```
156
+
157
+ Methods are called directly on element instances: `element.methodName()`
158
+
159
+ ---
160
+
161
+ ### 5. **Design System** (`/smbls/designSystem/`)
162
+
163
+ **Structure:**
164
+
165
+ Flat folder with individual files for each design aspect:
166
+
167
+ ```
168
+ designSystem/
169
+ ├── index.js # Registry with namespaces
170
+ ├── color.js # Color tokens
171
+ ├── spacing.js # Spacing/sizing scale
172
+ ├── typography.js # Typography definitions
173
+ ├── grid.js # Grid system
174
+ ├── theme.js # Theme definitions
175
+ ├── font.js # Font definitions
176
+ ├── icons.js # SVG icons (flat)
177
+ ├── animation.js # Animation definitions
178
+ ├── timing.js # Timing/duration values
179
+ └── ... # Other design tokens
180
+ ```
181
+
182
+ **File Pattern:**
183
+
184
+ ```javascript
185
+ // designSystem/color.js
186
+ export default {
187
+ black: '#000',
188
+ white: '#fff',
189
+ primary: '#0066cc',
190
+ secondary: '#666666',
191
+ };
192
+
193
+ // designSystem/spacing.js
194
+ export default {
195
+ base: 16,
196
+ ratio: 1.618,
197
+ };
198
+ ```
199
+
200
+ **Key Rules:**
201
+
202
+ - Each file exports a single design aspect as default object
203
+ - Organized by design concern: color, spacing, typography, grid, etc.
204
+ - Used in component properties through shorthand (e.g., `padding: 'A'`, `color: 'primary'`)
205
+
206
+ ---
207
+
208
+ ### 6. **State** (`/smbls/state/`)
209
+
210
+ **Structure:**
211
+
212
+ Flat folder for state and data files:
213
+
214
+ ```
215
+ state/
216
+ ├── index.js # Registry exporting all state
217
+ ├── metrics.js # Metrics data
218
+ └── ... # Other state files
219
+ ```
220
+
221
+ **File Pattern:**
222
+
223
+ ```javascript
224
+ // state/metrics.js
225
+ export default [
226
+ {
227
+ title: "Status",
228
+ items: [{ caption: "Live", value: 14 }],
229
+ },
230
+ // ...
231
+ ];
232
+ ```
233
+
234
+ **state/index.js:**
235
+
236
+ ```javascript
237
+ export default {
238
+ metrics: [],
239
+ user: {},
240
+ // ... initial state values inline — no imports
241
+ };
242
+ ```
243
+
244
+ > ⚠️ Do NOT import from other state files. Define all initial state inline in a single `state.js` or `state/index.js`.
245
+
246
+ **Key Rules:**
247
+
248
+ - State organized in folder with separate files by concern
249
+ - Each file exports default object with related state
250
+ - No logic or methods - only data structures
251
+ - Used as `state` parameter in component event handlers
252
+ - Accessed and modified through: `state.propertyName`
253
+
254
+ **Usage in Components:**
255
+
256
+ ```javascript
257
+ {
258
+ Button: {
259
+ onClick: (el, state) => {
260
+ state.user.authenticated = true;
261
+ console.log(state.metrics.status);
262
+ },
263
+ },
264
+ }
265
+ ```
266
+
267
+ ---
268
+
269
+ ### 7. **Variables** (`/smbls/vars.js`)
270
+
271
+ **File Pattern:**
272
+
273
+ ```javascript
274
+ // vars.js
275
+ export default {
276
+ // Global constants and settings
277
+ APP_VERSION: "1.0.0",
278
+ API_BASE_URL: "https://api.example.com",
279
+ };
280
+ ```
281
+
282
+ **Key Rules:**
283
+
284
+ - Global constants and application-wide settings
285
+ - Read-only values
286
+ - Reference in components: `onClick: (el, state) => { const url = state.root.vars.API_BASE_URL; }`
287
+
288
+ ---
289
+
290
+ ### 8. **Config** (`/smbls/config.js`)
291
+
292
+ **File Pattern:**
293
+
294
+ ```javascript
295
+ // config.js
296
+ export default {
297
+ useReset: true,
298
+ useVariable: true,
299
+ useFontImport: true,
300
+ useIconSprite: true,
301
+ useSvgSprite: true,
302
+ useDefaultConfig: true,
303
+ useDocumentTheme: true,
304
+ verbose: false,
305
+ };
306
+ ```
307
+
308
+ **Key Rules:**
309
+
310
+ - Single default export with platform/application configuration
311
+ - Boolean flags for feature toggles
312
+ - Settings that control runtime behavior
313
+ - Used internally by the DOMQL runtime
314
+ - Affects how components are rendered and styled
315
+
316
+ ---
317
+
318
+ ### 9. **Dependencies** (`/smbls/dependencies.js`)
319
+
320
+ **File Pattern:**
321
+
322
+ ```javascript
323
+ // dependencies.js - Fixed version numbers
324
+ export default {
325
+ "chart.js": "4.4.9",
326
+ "fuse.js": "7.1.0",
327
+ lit: "3.1.0",
328
+ "ninja-keys": "1.2.2",
329
+ };
330
+ ```
331
+
332
+ **Key Rules:**
333
+
334
+ - Maps external npm package names to **fixed version numbers**
335
+ - **NO module preloading** - packages defined here, imported on-demand
336
+ - Dynamic imports only within event handlers and functions via `await import()`
337
+ - Keeps structure resolvable without build step or package installation
338
+ - Version numbers must be exact and locked (no ranges like `^` or `~`)
339
+
340
+ **Dynamic Import Pattern:**
341
+
342
+ ```javascript
343
+ {
344
+ Button: {
345
+ onClick: async (element, state) => {
346
+ // Import at runtime when needed
347
+ const { Chart } = await import("chart.js");
348
+ const chart = new Chart(element, {
349
+ /* config */
350
+ });
351
+ };
352
+ }
353
+ }
354
+ ```
355
+
356
+ This approach ensures:
357
+
358
+ - No top-level imports clutter the file
359
+ - Packages loaded only when actually used
360
+ - Works in any environment (browser, server, file system)
361
+ - Declarative tree remains environment-agnostic
362
+ - Version consistency across environments
363
+
364
+ ---
365
+
366
+ ### 10. **Files** (`/smbls/files/`)
367
+
368
+ **File Pattern:**
369
+
370
+ ```javascript
371
+ // files/index.js - Asset manifest managed via Symbols SDK
372
+ // DO NOT manually edit this file
373
+ // To add files: Use Symbols SDK to upload, then place response data here
374
+
375
+ export default {
376
+ // ... file data managed by SDK
377
+ };
378
+ ```
379
+
380
+ **Key Rules:**
381
+
382
+ - Single default export mapping file keys to file metadata
383
+ - **Managed entirely via Symbols SDK** - do NOT manually create entries
384
+ - Use strict folder structure
385
+
386
+ **Adding Files:**
387
+
388
+ When the AI adds assets or files, it should use Symbols SDK commands to upload files and return related data to place in `files/`.
389
+
390
+ **Usage in Components:**
391
+
392
+ ```javascript
393
+ {
394
+ Image: {
395
+ src: 'Arbitrum.png',
396
+ // or rare occasions
397
+ src: (element, state, context) => context.files['Arbitrum.png'].content.src,
398
+ }
399
+ }
400
+ ```
401
+
402
+ ---
403
+
404
+ ### 11. **Fonts** (`/smbls/designSystem/fonts.js`)
405
+
406
+ **File Pattern:**
407
+
408
+ ```javascript
409
+ // designSystem/fonts.js - Fonts managed via Symbols SDK
410
+ // To add fonts: Upload via SDK, place response in this file
411
+
412
+ export default {
413
+ // ... font data managed by SDK
414
+ };
415
+ ```
416
+
417
+ **Key Rules:**
418
+
419
+ - Single default export with font definitions
420
+ - **Managed via Symbols SDK file upload** - don't add manually
421
+
422
+ **Adding Fonts:**
423
+
424
+ When adding fonts, use the SDK to upload and place the returned metadata in `designSystem/fonts.js`.
425
+
426
+ ---
427
+
428
+ ### 12. **Icons** (`/smbls/designSystem/icons.js`)
429
+
430
+ **File Pattern:**
431
+
432
+ ```javascript
433
+ // designSystem/icons.js - Flat SVG icon collection
434
+ export default {
435
+ logo: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7L12 12L22 7L12 2Z"/><path d="M2 17L12 22L22 17"/><path d="M2 12L12 17L22 12"/></svg>',
436
+
437
+ chevronLeft:
438
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>',
439
+
440
+ chevronRight:
441
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>',
442
+
443
+ search:
444
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>',
445
+
446
+ menu: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/></svg>',
447
+
448
+ close:
449
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',
450
+ };
451
+ ```
452
+
453
+ **Key Rules:**
454
+
455
+ - **Completely flat structure** - no nesting or categorization
456
+ - Each icon is a named property with inline SVG string
457
+ - Icon names in camelCase: `chevronLeft`, `arrowUp`, `checkmark`
458
+ - SVG uses `stroke="currentColor"` or `fill="currentColor"` for styling
459
+ - No folder structure or category prefixes
460
+
461
+ **Usage in Components:**
462
+
463
+ ```javascript
464
+ {
465
+ Icon: {
466
+ name: 'chevronLeft',
467
+ },
468
+
469
+ Button: {
470
+ extends: 'Button',
471
+ icon: 'search',
472
+ },
473
+ }
474
+ ```
475
+
476
+ ---
477
+
478
+ ### 13. **Snippets** (`/smbls/snippets/`)
479
+
480
+ **File Pattern:**
481
+
482
+ ```javascript
483
+ // snippets/index.js
484
+ export * from "./oneSnippet.js";
485
+ export * from "./dataSnippet.js";
486
+ ```
487
+
488
+ **Key Rules:**
489
+
490
+ - Reusable component or layout snippets
491
+ - Named exports of common patterns
492
+ - Used to reduce repetition of complex structures
493
+ - Can contain random snippets, JSON data, classes, functions, or any other reusable code
494
+ - **NOT** a component definition itself, but can be used within one
495
+
496
+ **Example Snippet:**
497
+
498
+ ```javascript
499
+ // snippets/dataMockSnippet.js
500
+ export const dataMockSnippet = {
501
+ data: [],
502
+ };
503
+ ```
504
+
505
+ **Usage in Components:**
506
+
507
+ ```javascript
508
+ {
509
+ List: {
510
+ // Reuse snippet pattern
511
+ children: (el, s, ctx) => el.getSnippet('dataMockSnippet').data
512
+ // or in rare occasions
513
+ children: (el, s, ctx) => ctx.snippets['dataMockSnippet'].data
514
+ },
515
+ Title: {
516
+ text: 'Hello'
517
+ }
518
+ }
519
+ ```
520
+
521
+ ---
522
+
523
+ ## Root Index Export (`/smbls/index.js`)
524
+
525
+ **Pattern:**
526
+
527
+ ```javascript
528
+ // smbls/index.js
529
+ export { default as config } from "./config.js";
530
+ export { default as vars } from "./vars.js";
531
+ export { default as dependencies } from "./dependencies.js";
532
+ export { default as designSystem } from "./designSystem/index.js";
533
+ export { default as state } from "./state/index.js";
534
+ export { default as files } from "./files/index.js";
535
+ export { default as pages } from "./pages/index.js";
536
+ export * as components from "./components/index.js";
537
+ export * as snippets from "./snippets/index.js";
538
+ export * as functions from "./functions/index.js";
539
+ export * as methods from "./methods/index.js";
540
+ ```
541
+
542
+ **Key Rules:**
543
+
544
+ - Central export point for entire project
545
+ - Exposes all modules with consistent naming
546
+ - Used by platform/framework to load the application
547
+ - Maintains structure for environment-agnostic loading
548
+
549
+ ---
550
+
551
+ ## Import Restrictions by Environment
552
+
553
+ ### ✅ ALLOWED Imports
554
+
555
+ 1. **Within same folder** (component to component via tree)
556
+
557
+ ```javascript
558
+ // No imports needed - reference by name
559
+ {
560
+ Header: { },
561
+ Content: { Search: { } }
562
+ }
563
+ ```
564
+
565
+ 2. **Function calls**
566
+
567
+ ```javascript
568
+ el.call("functionName", args);
569
+ ```
570
+
571
+ 3. **Method calls**
572
+ ```javascript
573
+ el.methodName();
574
+ ```
575
+
576
+ ### ❌ FORBIDDEN Imports
577
+
578
+ ```javascript
579
+ // DON'T DO THIS:
580
+ import { Header } from "./Header.js";
581
+ import { parseNetworkRow } from "../functions/parseNetworkRow.js";
582
+ import styles from "./style.css";
583
+ ```
584
+
585
+ No JavaScript `import`/`require` statements for components, functions, or methods within the project structure.
586
+
587
+ ---
588
+
589
+ ## File Structure Rules
590
+
591
+ ### Naming Conventions
592
+
593
+ | Location | Filename | Export | Type |
594
+ | --------------- | -------------------- | ----------------------------------------------- | --------------------- |
595
+ | `components/` | `Header.js` | `export const Header = { }` | PascalCase |
596
+ | `pages/` | `add-network.js` | `export const addNetwork = { }` | dash-case / camelCase |
597
+ | `functions/` | `parseNetworkRow.js` | `export const parseNetworkRow = function() { }` | camelCase |
598
+ | `methods/` | `formatDate.js` | `export const formatDate = function() { }` | camelCase |
599
+ | `designSystem/` | `color.js` | `export default { }` | camelCase |
600
+ | `snippets/` | `cardSnippet.js` | `export const cardSnippet = { }` | camelCase |
601
+ | `state/` | `metrics.js` | `export default [ ]` | camelCase |
602
+ | Root | `vars.js` | `export default { }` | camelCase |
603
+ | Root | `config.js` | `export default { }` | camelCase |
604
+ | Root | `dependencies.js` | `export default { }` | camelCase |
605
+ | Root | `files.js` | `export default { }` | camelCase |
606
+
607
+ ### Index Files & Root Exports
608
+
609
+ **[components/index.js](smbls/components/index.js):**
610
+
611
+ ```javascript
612
+ // CORRECT — flat re-exports, NOT 'export * as'
613
+ export * from "./ComponentName.js";
614
+ export * from "./AnotherComponent.js";
615
+ ```
616
+
617
+ > ⚠️ NEVER use `export * as ComponentName from '...'` — it wraps exports in a namespace object and breaks component resolution entirely.
618
+
619
+ **[functions/index.js](smbls/functions/index.js):**
620
+
621
+ ```javascript
622
+ export * from "./functionName.js";
623
+ ```
624
+
625
+ **[pages/index.js](smbls/pages/index.js):**
626
+
627
+ ```javascript
628
+ import { main } from "./main";
629
+ import { addNetwork } from "./add-network";
630
+ import { editNode } from "./edit-node";
631
+
632
+ export default {
633
+ "/": main,
634
+ "/add-network": addNetwork,
635
+ "/edit-node": editNode,
636
+ // ... route mappings
637
+ };
638
+ ```
639
+
640
+ **[snippets/index.js](smbls/snippets/index.js):**
641
+
642
+ ```javascript
643
+ export * from "./snippet1.js";
644
+ export * from "./snippet2.js";
645
+ ```
646
+
647
+ **[designSystem/index.js](smbls/designSystem/index.js):**
648
+
649
+ ```javascript
650
+ import ANIMATION from "./animation.js";
651
+ import COLOR from "./color.js";
652
+ import SPACING from "./spacing.js";
653
+ // ... all design system modules
654
+
655
+ export { ANIMATION, COLOR, SPACING };
656
+
657
+ export default {
658
+ ANIMATION,
659
+ COLOR,
660
+ SPACING,
661
+ // ...
662
+ };
663
+ ```
664
+
665
+ ---
666
+
667
+ ## Component Definition Template
668
+
669
+ ```javascript
670
+ export const ComponentName = {
671
+ // Extend from base component type
672
+ extends: "Flex", // or 'Box', 'Page', etc.
673
+
674
+ // Props: styling, behavior, event handlers
675
+ padding: "A",
676
+ theme: "dialog",
677
+ onClick: (el, s) => el.call("handleClick"),
678
+ onRender: async (el, s) => await el.call("fetchData"),
679
+
680
+ // Nested child components (no imports)
681
+ Header: {},
682
+ Content: {
683
+ Article: {
684
+ Title: { text: "Hello" },
685
+ },
686
+ },
687
+ Footer: {},
688
+ };
689
+ ```
690
+
691
+ ---
692
+
693
+ ## Component References: PascalCase Keys
694
+
695
+ **PascalCase keys automatically create components of that type.** You don't need to import them or use `extends:` when the key name matches the component name.
696
+
697
+ ### ❌ INCORRECT: Verbose with imports and extends
698
+
699
+ ```javascript
700
+ import { UpChart } from "./UpChart.js";
701
+ import { PeerCountChart } from "./PeerCountChart.js";
702
+
703
+ export const Graphs = {
704
+ UpChart: { extends: UpChart, props: { order: "1" } },
705
+ PeerCountChart: { extends: PeerCountChart, props: { flex: "1" } },
706
+ };
707
+ ```
708
+
709
+ **Problems:**
710
+
711
+ - Unnecessary imports clutter the file
712
+ - Verbose `extends:` and `props:` wrapper
713
+ - Redundant when key name matches component name
714
+
715
+ ### ✅ CORRECT: Clean PascalCase references
716
+
717
+ ```javascript
718
+ export const Graphs = {
719
+ UpChart: { order: "1" },
720
+ PeerCountChart: { flex: "1" },
721
+ };
722
+ ```
723
+
724
+ **Key Rules:**
725
+
726
+ - **Key name determines component type:** `UpChart:` automatically creates an `UpChart` component
727
+ - **No imports needed:** Component is referenced by name, not imported
728
+ - **Flatten props directly:** Put props inline, not in a `props:` wrapper
729
+ - **No `extends:` needed:** The key name is implicit `extends: ComponentName`
730
+ - **Works in all contexts:** Top-level, nested, or inside functions
731
+
732
+ ### Example: Rows of Charts
733
+
734
+ ```javascript
735
+ export const Graphs = {
736
+ extends: "Flex",
737
+
738
+ Row1: {
739
+ extends: "Flex",
740
+ flow: "x",
741
+ gap: "A",
742
+
743
+ // Each chart component is created by its PascalCase key
744
+ LatestBlockChart: { flex: "1" },
745
+ SyncingChart: { flex: "1" },
746
+ BlocksToSyncChart: { flex: "1" },
747
+ },
748
+
749
+ Row2: {
750
+ extends: "Flex",
751
+ flow: "x",
752
+ gap: "A",
753
+
754
+ PeerCountChart: { flex: "1" },
755
+ NetListeningChart: { flex: "1" },
756
+ },
757
+ };
758
+ ```
759
+
760
+ This approach keeps component definitions clean and readable while maintaining the declarative architecture principle.
761
+
762
+ ---
763
+
764
+ ## Event Handlers
765
+
766
+ ```javascript
767
+ {
768
+ Button: {
769
+ onClick: (element, state) => {
770
+ // Call function: el.call('functionName', ...args)
771
+ element.call("parseData", rawData);
772
+
773
+ // Call method: el.methodName()
774
+ element.format();
775
+
776
+ // Update state: state.property = value
777
+ state.count++;
778
+
779
+ // Use design system tokens in inline styles
780
+ element.style.padding = "A"; // From designSystem/spacing
781
+ };
782
+ }
783
+ }
784
+ ```
785
+
786
+ ---
787
+
788
+ ## Component Scope: Local Functions
789
+
790
+ When you need to define local helper functions within a component that are not meant for global reuse, use the `scope` property instead of importing external functions. This keeps the component self-contained and avoids creating unnecessary top-level imports.
791
+
792
+ ### ❌ INCORRECT: Importing Local Functions
793
+
794
+ ```javascript
795
+ // functions/fetchMetrics.js - If only used in one component!
796
+ const fetchMetrics = (timeRange) => {
797
+ // fetch logic
798
+ };
799
+
800
+ // components/Graphs.js
801
+ import { fetchMetrics } from "../functions/fetchMetrics.js"; // WRONG!
802
+
803
+ export const Graphs = {
804
+ extends: "Box",
805
+ onInit: (el) => {
806
+ fetchMetrics("week");
807
+ },
808
+ };
809
+ ```
810
+
811
+ **Problems:**
812
+
813
+ - Creates unnecessary separate files for component-specific logic
814
+ - Mixes component-specific and globally-reusable code
815
+ - Adds imports where they should be avoided
816
+
817
+ ### ✅ CORRECT: Use Component Scope
818
+
819
+ ```javascript
820
+ // components/Graphs.js
821
+ export const Graphs = {
822
+ extends: "Box",
823
+
824
+ // Define local functions in scope property
825
+ scope: {
826
+ fetchMetrics: (timeRange) => {
827
+ // fetch logic here - not exported, only used locally
828
+ return fetch(`/api/metrics?range=${timeRange}`).then((res) => res.json());
829
+ },
830
+
831
+ calculateAverage: (data) => {
832
+ return data.reduce((a, b) => a + b, 0) / data.length;
833
+ },
834
+ },
835
+
836
+ // Use scope functions in event handlers
837
+ onInit: (el) => {
838
+ const metrics = el.scope.fetchMetrics("week");
839
+ const avg = el.scope.calculateAverage(metrics);
840
+ },
841
+
842
+ Button: {
843
+ onClick: (el) => {
844
+ el.scope.fetchMetrics("month");
845
+ },
846
+ },
847
+ };
848
+ ```
849
+
850
+ **Key Rules for Scope:**
851
+
852
+ - `scope` property contains **local helper functions** for this component only
853
+ - Functions in scope are **never exported** and **never imported elsewhere**
854
+ - Access scope functions via `el.scope.functionName()`
855
+ - Use `scope` only for component-specific logic; use `functions/` for reusable utilities
856
+ - Scope functions receive only the data they need (element context is available via `el`)
857
+
858
+ ### Scope vs Functions Folder
859
+
860
+ **Use `scope` when:**
861
+
862
+ - Function is only used within one component
863
+ - Function is a helper for that specific component's logic
864
+ - Keeping code co-located improves readability
865
+
866
+ **Use `functions/` when:**
867
+
868
+ - Function is reused across multiple components
869
+ - Function is a general utility (parsing, calculations, data fetching patterns)
870
+ - Function can be tested independently
871
+
872
+ ### Example: Multiple Scope Functions
873
+
874
+ ```javascript
875
+ export const MetricsPage = {
876
+ extends: "Page",
877
+
878
+ scope: {
879
+ // Local helpers
880
+ fetchMetrics: async (type) => {
881
+ const res = await fetch(`/api/metrics/${type}`);
882
+ return res.json();
883
+ },
884
+
885
+ formatMetric: (value) => {
886
+ return new Intl.NumberFormat().format(value);
887
+ },
888
+
889
+ filterByEnvironment: (data, env) => {
890
+ return data.filter((item) => item.environment === env);
891
+ },
892
+ },
893
+
894
+ onInit: async (el, state) => {
895
+ const data = await el.scope.fetchMetrics("daily");
896
+ state.metrics = el.scope.filterByEnvironment(data, "production");
897
+ },
898
+
899
+ MetricsChart: {
900
+ onRender: (el, state) => {
901
+ const formatted = state.metrics.map((m) =>
902
+ el.scope.formatMetric(m.value),
903
+ );
904
+ el.data = formatted;
905
+ },
906
+ },
907
+ };
908
+ ```
909
+
910
+ ### Calling Global Functions from Scope
911
+
912
+ When a scope function needs to call a global function from the `functions/` folder, use `el.call()` instead of importing. **Pass `el` as the first parameter to the scope function so it has access to element methods.**
913
+
914
+ **Pattern:**
915
+
916
+ ```javascript
917
+ export const Graphs = {
918
+ extends: "Flex",
919
+
920
+ scope: {
921
+ // Scope function receives el as first parameter
922
+ fetchMetrics: (el, s, timeRange) => {
923
+ const networkName = (s.protocol || "").toLowerCase();
924
+
925
+ s.update({ metricsLoading: true });
926
+
927
+ // Call global function via el.call() - no import needed
928
+ el.call("apiFetch", "POST", "/api/metrics", {
929
+ networkName,
930
+ timeRangeMinutes: timeRange || 5,
931
+ })
932
+ .then((data) => {
933
+ s.update({ metricsData: data, metricsLoading: false });
934
+ })
935
+ .catch((err) => {
936
+ console.error("Failed to fetch:", err);
937
+ s.update({ metricsLoading: false });
938
+ });
939
+ },
940
+ },
941
+
942
+ onInit: (el, s) => {
943
+ // Pass el as first argument when calling scope function
944
+ el.scope.fetchMetrics(el, s, 5);
945
+ },
946
+ };
947
+ ```
948
+
949
+ **Key Rules:**
950
+
951
+ - **No imports needed** - Call global functions via `el.call('functionName', ...args)`
952
+ - **Pass `el` as first parameter** - Scope functions need element access to call `el.call()`
953
+ - **Update all call sites** - When calling the scope function, pass `el` as first argument
954
+ - **Keep scope for local logic only** - Use this pattern only in scope functions that need global utilities
955
+ - **No async/await in el.call()** - Handle promises with `.then()` and `.catch()`
956
+
957
+ ---
958
+
959
+ ## Environment Compatibility
960
+
961
+ This structure works seamlessly in:
962
+
963
+ - **VSCode** - Individual files can be edited independently
964
+ - **Symbols Platform** - Declarative trees render directly
965
+ - **File Structure** - Pure JavaScript, no build step required
966
+ - **Server Rendering** - Stateless object definitions
967
+ - **Web Browser** - DOMQL runtime interprets the tree
968
+
969
+ **No special handling needed** - the same files work everywhere.
970
+
971
+ ---
972
+
973
+ ## DO's and DON'Ts
974
+
975
+ ### ✅ DO:
976
+
977
+ - Name files exactly as their export names
978
+ - Use declarative object syntax for all components and pages
979
+ - Components MUST be plain JavaScript objects, never functions
980
+ - Reference components by name within the tree
981
+ - Use `el.call('functionName')` for utilities
982
+ - Use design system shorthand in props
983
+ - Keep components stateless (state managed externally)
984
+ - Place all component logic into props handlers
985
+ - Keep all folders flat - no subfolders within components/, functions/, etc.
986
+
987
+ ### ❌ DON'T:
988
+
989
+ - Import components as JavaScript modules
990
+ - Use `import/require` for project files
991
+ - Create class-based components
992
+ - **Use component functions** - components must be objects, never callable functions
993
+ - Mix framework-specific code (React, Vue, etc.)
994
+ - Mutate element directly (use state instead)
995
+ - Create circular dependencies between files
996
+ - Use default exports for components (use named exports)
997
+ - **Create subfolders** - Anti-pattern to have `components/charts/`, `functions/api/`, etc. All files must be flat
998
+
999
+ ---
1000
+
1001
+ ## Flat Folder Structure (No Subfolders)
1002
+
1003
+ All folders must remain completely flat. Creating subfolders is an anti-pattern that breaks the architecture.
1004
+
1005
+ ### ❌ INCORRECT: Organizing with Subfolders
1006
+
1007
+ ```javascript
1008
+ // WRONG - Don't do this!
1009
+ components/
1010
+ ├── charts/
1011
+ │ ├── LineChart.js
1012
+ │ ├── BarChart.js
1013
+ │ └── PieChart.js
1014
+ ├── forms/
1015
+ │ ├── LoginForm.js
1016
+ │ ├── RegisterForm.js
1017
+ │ └── ContactForm.js
1018
+ └── Button.js
1019
+
1020
+ functions/
1021
+ ├── api/
1022
+ │ ├── fetchUser.js
1023
+ │ ├── fetchPosts.js
1024
+ │ └── deleteUser.js
1025
+ ├── math/
1026
+ │ └── calculateCosts.js
1027
+ └── ...
1028
+ ```
1029
+
1030
+ **Problems:**
1031
+
1032
+ - Import paths become complex and variable
1033
+ - File registry in `index.js` becomes harder to maintain
1034
+ - Path resolution differs between environments
1035
+ - Contradicts flat, declarative principle
1036
+ - Makes search and discovery harder
1037
+
1038
+ ### ✅ CORRECT: Completely Flat Structure
1039
+
1040
+ ```javascript
1041
+ // RIGHT - Always do this
1042
+ components/
1043
+ ├── index.js
1044
+ ├── Header.js
1045
+ ├── Button.js
1046
+ ├── LineChart.js
1047
+ ├── BarChart.js
1048
+ ├── PieChart.js
1049
+ ├── LoginForm.js
1050
+ ├── RegisterForm.js
1051
+ ├── ContactForm.js
1052
+ └── ...
1053
+
1054
+ functions/
1055
+ ├── index.js
1056
+ ├── parseNetworkRow.js
1057
+ ├── calculateCosts.js
1058
+ ├── fetchUser.js
1059
+ ├── fetchPosts.js
1060
+ ├── deleteUser.js
1061
+ └── ...
1062
+ ```
1063
+
1064
+ **Advantages:**
1065
+
1066
+ - Simple, predictable file structure
1067
+ - Consistent import paths: `./ComponentName.js`
1068
+ - Easy to maintain and search
1069
+ - Works identically in all environments
1070
+ - Clear naming eliminates need for folders
1071
+ - All files registered at the same level in `index.js`
1072
+
1073
+ ### Naming Strategy Instead of Folders:
1074
+
1075
+ Use **descriptive filenames** instead of subfolders to organize conceptually-related files:
1076
+
1077
+ ```javascript
1078
+ // components/ - Chart-related components
1079
+ ChartContainer.js;
1080
+ LineChart.js;
1081
+ BarChart.js;
1082
+ PieChart.js;
1083
+ ChartTooltip.js;
1084
+ ChartLegend.js;
1085
+
1086
+ // functions/ - Function-related APIs
1087
+ fetchUserProfile.js;
1088
+ fetchUserPosts.js;
1089
+ deleteUserAccount.js;
1090
+ createNewPost.js;
1091
+ ```
1092
+
1093
+ Each filename clearly indicates its purpose without needing folder organization.
1094
+
1095
+ ---
1096
+
1097
+ ## Components are Objects, Not Functions
1098
+
1099
+ This is a critical architectural principle. Components must ALWAYS be plain JavaScript objects, never functions.
1100
+
1101
+ ### ❌ INCORRECT: Component as a Function
1102
+
1103
+ ```javascript
1104
+ // WRONG - Don't do this!
1105
+ export const Header = (element, state) => ({
1106
+ border: "1px solid black",
1107
+ padding: "A",
1108
+ Title: {
1109
+ text: "Hello",
1110
+ },
1111
+ });
1112
+ ```
1113
+
1114
+ **Problems:**
1115
+
1116
+ - Runtime recalculation on every access
1117
+ - Stateful behavior contradicts declarative principle
1118
+ - Cannot be properly registered and cached
1119
+ - Breaks environment-agnostic loading
1120
+
1121
+ ### ✅ CORRECT: Component as a Plain Object
1122
+
1123
+ ```javascript
1124
+ // RIGHT - Always do this
1125
+ export const Header = {
1126
+ border: "1px solid black",
1127
+ padding: "A",
1128
+ Title: {
1129
+ text: "Hello",
1130
+ },
1131
+ onClick: (element, state) => {
1132
+ // Logic goes in handlers, not in the object definition
1133
+ state.count++;
1134
+ },
1135
+ };
1136
+ ```
1137
+
1138
+ **Why:**
1139
+
1140
+ - Static, declarative definition
1141
+ - Resolvable without runtime execution
1142
+ - Cacheable and registrable
1143
+ - Works in all environments (VSCode, server, browser, Symbols platform)
1144
+ - Handlers can contain logic at runtime
1145
+
1146
+ ### Key Point:
1147
+
1148
+ **Only property values can be functions (event handlers, getters), never the component itself.**
1149
+
1150
+ ---
1151
+
1152
+ ## Example: Building a Feature
1153
+
1154
+ ### Task: Create a User Profile Card Component
1155
+
1156
+ **1. Create** `components/UserCard.js`:
1157
+
1158
+ ```javascript
1159
+ export const UserCard = {
1160
+ extends: "Box",
1161
+ padding: "A2",
1162
+ round: "A",
1163
+ background: "white",
1164
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
1165
+ Avatar: {
1166
+ boxSize: "C",
1167
+ },
1168
+ Name: {
1169
+ fontSize: "L",
1170
+ fontWeight: "600",
1171
+ },
1172
+ Email: {
1173
+ fontSize: "S",
1174
+ color: "caption",
1175
+ },
1176
+ Actions: {
1177
+ Edit: {
1178
+ onClick: (el) => el.call("editUser"),
1179
+ },
1180
+ Delete: {
1181
+ onClick: (el) => el.call("deleteUser"),
1182
+ },
1183
+ },
1184
+ };
1185
+ ```
1186
+
1187
+ **2. Create** `functions/editUser.js`:
1188
+
1189
+ ```javascript
1190
+ export const editUser = function (userId) {
1191
+ return fetch(`/api/users/${userId}`, { method: "GET" }).then((res) =>
1192
+ res.json(),
1193
+ );
1194
+ };
1195
+ ```
1196
+
1197
+ **3. Use in page** `pages/profile.js`:
1198
+
1199
+ ```javascript
1200
+ export const profile = {
1201
+ extends: "Page",
1202
+ UserCard: {
1203
+ // No import needed!
1204
+ },
1205
+ };
1206
+ ```
1207
+
1208
+ **4. Register in** `components/index.js`:
1209
+
1210
+ ```javascript
1211
+ // CORRECT — flat re-export
1212
+ export * from "./UserCard.js";
1213
+ ```
1214
+
1215
+ ---
1216
+
1217
+ ## Summary
1218
+
1219
+ This is a **strict, declarative architecture** where:
1220
+
1221
+ 1. **Each file exports one independent object** (component, function, or method)
1222
+ 2. **No JavaScript imports between project files** - Everything is registered in index files
1223
+ 3. **Components reference each other by name** in the object tree
1224
+ 4. **Functions/methods are called at runtime** via `element.call()` and `element.method()`
1225
+ 5. **Design tokens are available globally** through shorthand notation
1226
+ 6. **Works everywhere** - VSCode, Symbols platform, servers, browsers - without modification
1227
+
1228
+ The design enables **framework-agnostic, environment-independent code** while maintaining **strict structure and conventions**.
1229
+
1230
+ ---
1231
+
1232
+ ## Complete Project Structure Overview
1233
+
1234
+ ```
1235
+ smbls/
1236
+ ├── index.js # Root export (central loader)
1237
+ ├── vars.js # Global variables/constants
1238
+ ├── config.js # Platform configuration
1239
+ ├── dependencies.js # External npm packages (fixed versions)
1240
+
1241
+ ├── components/ # UI Components (PascalCase files)
1242
+ │ ├── index.js # Component registry
1243
+ │ ├── Header.js
1244
+ │ ├── Button.js
1245
+ │ ├── Modal.js
1246
+ │ └── ...
1247
+
1248
+ ├── pages/ # Page layouts (dash-case files)
1249
+ │ ├── index.js # Route mapping
1250
+ │ ├── main.js
1251
+ │ ├── add-network.js # dash-case filename, camelCase export
1252
+ │ ├── edit-node.js
1253
+ │ ├── dashboard.js
1254
+ │ └── ...
1255
+
1256
+ ├── functions/ # Utility functions (camelCase)
1257
+ │ ├── index.js # Function exports
1258
+ │ ├── parseNetworkRow.js
1259
+ │ ├── calculateCosts.js
1260
+ │ └── ...
1261
+
1262
+ ├── methods/ # Element methods (camelCase)
1263
+ │ ├── index.js
1264
+ │ └── ...
1265
+
1266
+ ├── state/ # State and data (flat folder)
1267
+ │ ├── index.js # State registry
1268
+ │ ├── metrics.js
1269
+ │ ├── user.js
1270
+ │ ├── fleet.js
1271
+ │ └── ...
1272
+
1273
+ ├── files/ # File assets (flat folder)
1274
+ │ ├── index.js # Files registry
1275
+ │ ├── images.js
1276
+ │ ├── logos.js
1277
+ │ └── ...
1278
+
1279
+ ├── designSystem/ # Design tokens (flat folder)
1280
+ │ ├── index.js # Token registry with namespaces
1281
+ │ ├── color.js # Color tokens
1282
+ │ ├── spacing.js # Spacing/sizing scale
1283
+ │ ├── typography.js # Typography definitions
1284
+ │ ├── grid.js # Grid system
1285
+ │ ├── theme.js # Theme definitions
1286
+ │ ├── fonts.js # Font definitions
1287
+ │ ├── icons.js # SVG icons (flat)
1288
+ │ ├── animation.js # Animation definitions
1289
+ │ ├── timing.js # Timing values
1290
+ │ └── ...
1291
+
1292
+ └── snippets/ # Reusable code/data (any type)
1293
+ ├── index.js # Snippet registry
1294
+ ├── cardSnippet.js # Component snippets
1295
+ ├── mockData.js # Mock data
1296
+ ├── constants.js # Constants/enums
1297
+ ├── utils.js # Utility functions
1298
+ ├── response.json # Response examples
1299
+ └── ...
1300
+ ```
1301
+
1302
+ **Key Structural Points:**
1303
+
1304
+ - `state/` and `files/` are **folders with index.js registry**, not single files
1305
+ - All folders are **completely flat** - no subfolders within any folder
1306
+ - `designSystem/` is completely flat with separate files for each design aspect
1307
+ - `snippets/` can contain ANY type of JavaScript: components, functions, data, JSON
1308
+ - Clear naming conventions eliminate need for folder organization
1309
+
1310
+ ---
1311
+
1312
+ ## Zero Compilation Principle
1313
+
1314
+ **This structure is completely resolvable without any build step, compilation, or bundling.**
1315
+
1316
+ ### Why It Works Everywhere:
1317
+
1318
+ 1. **Pure JavaScript Objects** - No JSX, no preprocessing, just plain object literals
1319
+ 2. **Dynamic Imports Only in Handlers** - NPM packages imported via `await import()` inside event listeners, never at module level
1320
+ 3. **No Circular Dependencies** - Declarative tree structure prevents cyclic imports
1321
+ 4. **Stateless by Design** - Each file is independent; state managed externally
1322
+ 5. **Direct File Resolution** - No alias resolution needed; files imported directly by path
1323
+
1324
+ ### Environment Loading:
1325
+
1326
+ - **VSCode:** Each `.js` file is a standalone module; syntax check works immediately
1327
+ - **Symbols Platform:** Parses the entire tree; renders components declaratively
1328
+ - **Browser:** DOMQL runtime loads and interprets the tree; imports handled by browser `import()`
1329
+ - **Server:** Node.js executes the tree; dynamic imports work natively
1330
+ - **File System:** Can be read and processed as plain JavaScript objects
1331
+
1332
+ **Result:** The exact same files work in all environments without modification.
1333
+
1334
+ ---
1335
+
1336
+ ## Best Practices Summary
1337
+
1338
+ ### ✅ Best Practices:
1339
+
1340
+ - **One export per file** - Keeps structure clear and resolvable
1341
+ - **Declarative over imperative** - Use object structures, not code execution
1342
+ - **Import dependencies dynamically** - Only when needed in event handlers
1343
+ - **Reference components by name** - The tree handles all resolution
1344
+ - **Keep functions pure** - No side effects, only transformations
1345
+ - **Store state separately** - Never mutate component definitions
1346
+ - **Use design tokens** - Never hardcode styles or values
1347
+ - **Keep files small** - Easy to read, test, and maintain
1348
+
1349
+ ### ❌ Anti-Patterns:
1350
+
1351
+ - Top-level `import`/`require` of project files
1352
+ - Class-based components or inheritance
1353
+ - Framework-specific syntax (React hooks, Vue composables)
1354
+ - Circular module dependencies
1355
+ - Hardcoded values in component definitions
1356
+ - Dynamic property names in object keys
1357
+ - Side effects in function definitions
1358
+
1359
+ ---
1360
+
1361
+ ## Migration Guide: Converting Old Projects
1362
+
1363
+ If converting from a standard module-based architecture:
1364
+
1365
+ 1. **Remove all imports** of local project modules
1366
+ 2. **Convert all components to plain objects** - No function wrappers, no factory functions
1367
+ 3. **Convert props to declarative objects** - No function closures, just data
1368
+ 4. **Move state to `state/` folder** - Centralize all mutable data
1369
+ 5. **Replace function calls with `el.call()`** - Dynamic dispatch instead of imports
1370
+ 6. **Move dynamic dependencies to handlers** - Use `await import()` inside events
1371
+ 7. **Rename components to PascalCase** - Consistent with component convention
1372
+ 8. **Update index files** - Register all exports centrally
1373
+
1374
+ Example transformation:
1375
+
1376
+ ```javascript
1377
+ // OLD (Framework style)
1378
+ import Button from "./Button.js";
1379
+ import { handleClick } from "./handlers.js";
1380
+
1381
+ export const Header = () => {
1382
+ return <Button onClick={handleClick} />;
1383
+ };
1384
+
1385
+ // NEW (Symbols style)
1386
+ // state/index.js
1387
+ export default { clickCount: 0 };
1388
+
1389
+ // components/Header.js
1390
+ export const Header = {
1391
+ Button: {
1392
+ onClick: (el, state) => {
1393
+ state.clickCount++;
1394
+ el.call("logClick", state.clickCount);
1395
+ },
1396
+ },
1397
+ };
1398
+
1399
+ // functions/logClick.js
1400
+ export const logClick = function (count) {
1401
+ console.log("Clicks:", count);
1402
+ };
1403
+ ```
1404
+
1405
+ This architecture ensures **true independence** of components, **zero runtime compilation**, and **environment agnostic** execution.