@techninja/clearstack 0.2.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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/bin/cli.js +62 -0
  4. package/docs/BACKEND_API_SPEC.md +281 -0
  5. package/docs/BUILD_LOG.md +193 -0
  6. package/docs/COMPONENT_PATTERNS.md +481 -0
  7. package/docs/CONVENTIONS.md +226 -0
  8. package/docs/FRONTEND_IMPLEMENTATION_RULES.md +239 -0
  9. package/docs/JSDOC_TYPING.md +86 -0
  10. package/docs/QUICKSTART.md +190 -0
  11. package/docs/SERVER_AND_DEPS.md +163 -0
  12. package/docs/STATE_AND_ROUTING.md +363 -0
  13. package/docs/TESTING.md +268 -0
  14. package/docs/app-spec/ENTITIES.md +37 -0
  15. package/docs/app-spec/README.md +19 -0
  16. package/lib/check.js +115 -0
  17. package/lib/copy.js +43 -0
  18. package/lib/init.js +73 -0
  19. package/lib/package-gen.js +83 -0
  20. package/lib/update.js +73 -0
  21. package/package.json +69 -0
  22. package/templates/fullstack/data/seed.json +1 -0
  23. package/templates/fullstack/src/api/db.js +75 -0
  24. package/templates/fullstack/src/api/entities.js +114 -0
  25. package/templates/fullstack/src/api/events.js +35 -0
  26. package/templates/fullstack/src/api/schemas.js +104 -0
  27. package/templates/fullstack/src/api/validate.js +52 -0
  28. package/templates/fullstack/src/pages/home/home-view.js +19 -0
  29. package/templates/fullstack/src/router/index.js +16 -0
  30. package/templates/fullstack/src/server.js +46 -0
  31. package/templates/fullstack/src/store/AppState.js +33 -0
  32. package/templates/fullstack/src/store/UserPrefs.js +31 -0
  33. package/templates/fullstack/src/store/realtimeSync.js +54 -0
  34. package/templates/shared/.configs/.prettierrc +8 -0
  35. package/templates/shared/.configs/eslint.config.js +64 -0
  36. package/templates/shared/.configs/jsconfig.json +24 -0
  37. package/templates/shared/.configs/web-test-runner.config.js +8 -0
  38. package/templates/shared/.env +9 -0
  39. package/templates/shared/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
  40. package/templates/shared/.github/ISSUE_TEMPLATE/feature_request.md +30 -0
  41. package/templates/shared/.github/ISSUE_TEMPLATE/spec_correction.md +26 -0
  42. package/templates/shared/.github/pull_request_template.md +51 -0
  43. package/templates/shared/.github/workflows/spec.yml +46 -0
  44. package/templates/shared/README.md +22 -0
  45. package/templates/shared/docs/app-spec/README.md +40 -0
  46. package/templates/shared/docs/clearstack/BACKEND_API_SPEC.md +281 -0
  47. package/templates/shared/docs/clearstack/BUILD_LOG.md +193 -0
  48. package/templates/shared/docs/clearstack/COMPONENT_PATTERNS.md +481 -0
  49. package/templates/shared/docs/clearstack/CONVENTIONS.md +226 -0
  50. package/templates/shared/docs/clearstack/FRONTEND_IMPLEMENTATION_RULES.md +239 -0
  51. package/templates/shared/docs/clearstack/JSDOC_TYPING.md +86 -0
  52. package/templates/shared/docs/clearstack/QUICKSTART.md +190 -0
  53. package/templates/shared/docs/clearstack/SERVER_AND_DEPS.md +163 -0
  54. package/templates/shared/docs/clearstack/STATE_AND_ROUTING.md +363 -0
  55. package/templates/shared/docs/clearstack/TESTING.md +268 -0
  56. package/templates/shared/public/index.html +26 -0
  57. package/templates/shared/scripts/build-icons.js +86 -0
  58. package/templates/shared/scripts/vendor-deps.js +25 -0
  59. package/templates/shared/src/components/atoms/app-badge/app-badge.css +4 -0
  60. package/templates/shared/src/components/atoms/app-badge/app-badge.js +23 -0
  61. package/templates/shared/src/components/atoms/app-badge/app-badge.test.js +26 -0
  62. package/templates/shared/src/components/atoms/app-badge/index.js +1 -0
  63. package/templates/shared/src/components/atoms/app-button/app-button.css +3 -0
  64. package/templates/shared/src/components/atoms/app-button/app-button.js +41 -0
  65. package/templates/shared/src/components/atoms/app-button/app-button.test.js +43 -0
  66. package/templates/shared/src/components/atoms/app-button/index.js +1 -0
  67. package/templates/shared/src/components/atoms/app-icon/app-icon.css +4 -0
  68. package/templates/shared/src/components/atoms/app-icon/app-icon.js +57 -0
  69. package/templates/shared/src/components/atoms/app-icon/app-icon.test.js +30 -0
  70. package/templates/shared/src/components/atoms/app-icon/index.js +1 -0
  71. package/templates/shared/src/components/atoms/theme-toggle/index.js +1 -0
  72. package/templates/shared/src/components/atoms/theme-toggle/theme-toggle.css +10 -0
  73. package/templates/shared/src/components/atoms/theme-toggle/theme-toggle.js +42 -0
  74. package/templates/shared/src/styles/buttons.css +79 -0
  75. package/templates/shared/src/styles/components.css +31 -0
  76. package/templates/shared/src/styles/forms.css +20 -0
  77. package/templates/shared/src/styles/reset.css +32 -0
  78. package/templates/shared/src/styles/shared.css +135 -0
  79. package/templates/shared/src/styles/tokens.css +65 -0
  80. package/templates/shared/src/utils/formatDate.js +41 -0
  81. package/templates/shared/src/utils/statusColors.js +60 -0
  82. package/templates/static/src/pages/home/home-view.js +38 -0
  83. package/templates/static/src/router/index.js +16 -0
  84. package/templates/static/src/store/AppState.js +26 -0
@@ -0,0 +1,239 @@
1
+ # Frontend Implementation Rules
2
+ ## Hybrids.js "No-Build" Web Component Specification
3
+
4
+ > A concise, LLM-and-human-friendly specification for building web applications
5
+ > with Hybrids v9 using ES modules, no bundler, and atomic design principles.
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ **This file:** Foundation — philosophy, framework, structure, atomic design.
12
+
13
+ 1. [Philosophy & Constraints](#1-philosophy--constraints)
14
+ 2. [Framework Choice: Hybrids.js](#2-framework-choice-hybridsjs)
15
+ 3. [Project Structure](#3-project-structure)
16
+ 4. [Atomic Design Hierarchy](#4-atomic-design-hierarchy)
17
+
18
+ **Sub-specifications:**
19
+
20
+ | Document | Covers |
21
+ |---|---|
22
+ | [COMPONENT_PATTERNS.md](./COMPONENT_PATTERNS.md) | Authoring, light DOM, styling, layout engine, file size rules |
23
+ | [JSDOC_TYPING.md](./JSDOC_TYPING.md) | JSDoc typing strategy, tsc validation, component/model/handler patterns |
24
+ | [STATE_AND_ROUTING.md](./STATE_AND_ROUTING.md) | Store, routing, unified app state, realtime sync |
25
+ | [CONVENTIONS.md](./CONVENTIONS.md) | Naming conventions, anti-patterns |
26
+ | [SERVER_AND_DEPS.md](./SERVER_AND_DEPS.md) | Express server, import maps, vendor dependency loading |
27
+ | [BACKEND_API_SPEC.md](./BACKEND_API_SPEC.md) | REST endpoints, JSON Schema via HEAD, entity CRUD, realtime sync |
28
+ | [TESTING.md](./TESTING.md) | Testing philosophy, tools, patterns, build-phase checkpoints |
29
+
30
+ ---
31
+
32
+ ## 1. Philosophy & Constraints
33
+
34
+ This specification defines a **zero-build** frontend architecture. No bundler,
35
+ no transpiler, no compile step. Code runs exactly as written.
36
+
37
+ ### Core Principles
38
+
39
+ | Principle | Rule |
40
+ |---|---|
41
+ | No build tools | No Webpack, Vite, Rollup, esbuild, or Babel |
42
+ | ES modules only | All `.js` files are native ES modules served to the browser |
43
+ | Import maps | Bare specifiers (e.g. `"hybrids"`) resolved via `<script type="importmap">` |
44
+ | Small files | Every file ≤ **150 lines** before extracting shared logic |
45
+ | Explicit over implicit | Name things clearly; avoid magic strings and hidden conventions |
46
+ | Readable over clever | Optimize for comprehension by humans and LLMs alike |
47
+ | Declarative over imperative | Use framework patterns, not raw DOM manipulation |
48
+ | Composition over inheritance | Build complex UIs by composing small components |
49
+
50
+ ### What This Means in Practice
51
+
52
+ - You can open any `.js` file in the browser devtools and see the source as-is.
53
+ - Adding a new component means creating files and importing them — no config.
54
+ - Third-party dependencies are vendored as ES modules at install time.
55
+ - The server is a thin static file host with no middleware transforms.
56
+
57
+ ### Constraints
58
+
59
+ - **No TypeScript** — plain JavaScript with JSDoc comments where types help.
60
+ - **No CSS preprocessors** — plain CSS with custom properties for tokens.
61
+ - **No framework CLI** — manual file creation following this spec's conventions.
62
+ - **No dynamic `import()` for core components** — static imports for the
63
+ dependency graph to remain visible and traceable.
64
+ - **Node.js ≥ 18** — required for the Express server and `--watch` flag.
65
+
66
+ ---
67
+
68
+ ## 2. Framework Choice: Hybrids.js
69
+
70
+ We use **[Hybrids v9](https://hybrids.js.org)** — a functional, declarative
71
+ web component framework built on plain objects and pure functions.
72
+
73
+ ### Why Hybrids
74
+
75
+ | Need | Hybrids Provides |
76
+ |---|---|
77
+ | Components | `define()` — plain object definitions, no classes |
78
+ | Templating | `html``` — tagged template literals with reactive bindings |
79
+ | State | `store()` — global state with async storage, caching, relations |
80
+ | Routing | `router()` — view-graph-based routing with guards and dialogs |
81
+ | Layout | `layout=""` attribute — CSS layout engine in templates |
82
+ | Localization | `localize()` — automatic template translation |
83
+ | ES modules | Ships as raw ES modules in `src/` — no build needed |
84
+
85
+ ### API Surface (v9.1)
86
+
87
+ These are the only imports you need:
88
+
89
+ ```javascript
90
+ import {
91
+ define, // Register a component
92
+ html, // Template tagged literal
93
+ store, // State management
94
+ router, // Routing
95
+ mount, // Mount component on existing element
96
+ parent, // Access parent component
97
+ children, // Access child components
98
+ dispatch, // Dispatch custom events
99
+ msg, // Localization messages
100
+ localize, // Register translations
101
+ } from 'hybrids';
102
+ ```
103
+
104
+ ### Why Not Alternatives
105
+
106
+ | Alternative | Reason to pass |
107
+ |---|---|
108
+ | **Lit** | Class-based, heavier API surface, decorators encourage build tools |
109
+ | **Stencil** | Requires a compiler — violates no-build constraint |
110
+ | **Vanilla** | No state management, no templating — too much boilerplate |
111
+ | **React/Vue/Svelte** | Require build steps, not native web components |
112
+
113
+ ---
114
+
115
+ ## 3. Project Structure
116
+
117
+ ```
118
+ project-root/
119
+ ├── public/ # Static assets served at /
120
+ │ ├── index.html # App shell with import map
121
+ │ └── vendor/ # Vendored ES module deps (generated)
122
+ │ └── hybrids/ # Copied from node_modules at install
123
+
124
+ ├── src/ # Application source (served at /src/)
125
+ │ ├── components/ # UI components (atomic design)
126
+ │ │ ├── atoms/ # Smallest UI primitives
127
+ │ │ │ └── app-button/
128
+ │ │ │ ├── app-button.js # Component definition
129
+ │ │ │ ├── app-button.css # Scoped styles
130
+ │ │ │ └── index.js # Re-export
131
+ │ │ ├── molecules/ # Compositions of atoms
132
+ │ │ │ └── search-bar/
133
+ │ │ ├── organisms/ # Complex UI sections
134
+ │ │ │ └── app-header/
135
+ │ │ └── templates/ # Page-level layout shells
136
+ │ │ └── page-layout/
137
+ │ │
138
+ │ ├── pages/ # Route-bound view components
139
+ │ │ ├── home/
140
+ │ │ │ ├── home-view.js
141
+ │ │ │ └── index.js
142
+ │ │ └── about/
143
+ │ │
144
+ │ ├── store/ # Hybrids store model definitions
145
+ │ │ ├── AppState.js # Singleton: global app state
146
+ │ │ └── UserModel.js # Enumerable: user records
147
+ │ │
148
+ │ ├── router/ # Router shell component
149
+ │ │ └── index.js
150
+ │ │
151
+ │ ├── styles/ # Shared CSS
152
+ │ │ ├── tokens.css # Design tokens (colors, spacing)
153
+ │ │ └── reset.css # Minimal CSS reset
154
+ │ │
155
+ │ └── utils/ # Pure helper functions
156
+ │ └── formatDate.js
157
+
158
+ ├── scripts/ # Build/install scripts
159
+ │ └── vendor-deps.js # Copies deps to public/vendor/
160
+
161
+ ├── src/server.js # Express entry point
162
+ ├── package.json # type: "module", postinstall hook
163
+ ├── README.md # Project overview
164
+ └── FRONTEND_IMPLEMENTATION_RULES.md # This file
165
+ ```
166
+
167
+ ### Key Conventions
168
+
169
+ - **One component per directory.** Each gets its own folder with `.js`, `.css`,
170
+ and `index.js` (re-export).
171
+ - **`src/` is served as-is** — the browser loads these files directly.
172
+ - **`public/vendor/`** is gitignored and regenerated on `npm install` via the
173
+ `postinstall` script.
174
+ - **No barrel files** beyond the per-component `index.js`. Import from the
175
+ component directory, not from a giant `components/index.js`.
176
+ - **Pages are not components.** They live in `src/pages/`, not in
177
+ `src/components/`. They compose components but are themselves route targets.
178
+
179
+ ---
180
+
181
+ ## 4. Atomic Design Hierarchy
182
+
183
+ Components are organized into four tiers. Each tier has a clear scope and
184
+ import direction: **higher tiers import from lower tiers, never the reverse.**
185
+
186
+ ### Tiers
187
+
188
+ | Tier | Location | Scope | Examples |
189
+ |---|---|---|---|
190
+ | **Atom** | `components/atoms/` | Single-purpose UI primitive. One element, one job. | `app-button`, `app-icon`, `app-input` |
191
+ | **Molecule** | `components/molecules/` | Small composition of 2–4 atoms that form a reusable unit. | `nav-link`, `search-bar`, `form-field` |
192
+ | **Organism** | `components/organisms/` | Complex UI section. May contain molecules, atoms, and local state. | `app-header`, `app-footer`, `user-card` |
193
+ | **Template** | `components/templates/` | Page-level layout shell. Defines slot regions, no business logic. | `page-layout`, `dashboard-layout` |
194
+
195
+ **Pages** (`src/pages/`) sit outside the component hierarchy. They are
196
+ route-bound views that compose templates and organisms.
197
+
198
+ ### Import Direction
199
+
200
+ ```
201
+ Pages → Templates → Organisms → Molecules → Atoms
202
+
203
+ Store / Utils
204
+ ```
205
+
206
+ - Atoms import **nothing** from other component tiers.
207
+ - Molecules import only from **atoms**.
208
+ - Organisms import from **molecules** and **atoms**.
209
+ - Templates import from **organisms**, **molecules**, and **atoms**.
210
+ - Pages import from **any component tier** and from **store/router**.
211
+ - **Store models and utils** are shared — any tier may import them.
212
+
213
+ ### When to Promote a Component
214
+
215
+ Use this checklist to decide if a component belongs at a higher tier:
216
+
217
+ | Signal | Action |
218
+ |---|---|
219
+ | It renders a single HTML element with props | Keep as **atom** |
220
+ | It composes 2–4 atoms into a reusable group | Make it a **molecule** |
221
+ | It has its own local state or fetches data | Promote to **organism** |
222
+ | It defines layout regions via slots, no logic | Make it a **template** |
223
+ | It's bound to a route and composes a full page | Put it in **pages/** |
224
+
225
+ ### File Anatomy (All Tiers)
226
+
227
+ Every component directory contains exactly three files:
228
+
229
+ ```
230
+ app-button/
231
+ ├── app-button.js # Component definition (define + html + logic)
232
+ ├── app-button.css # Scoped styles for this component
233
+ └── index.js # export { default } from './app-button.js';
234
+ ```
235
+
236
+ If a component needs helpers that push it past 150 lines, extract them to
237
+ `src/utils/` — not into sibling files within the component directory.
238
+
239
+
@@ -0,0 +1,86 @@
1
+ # JSDoc Typing Strategy
2
+ ## Type Safety Without TypeScript
3
+
4
+ > JSDoc annotations provide editor intellisense, LLM comprehension, and
5
+ > compile-time type checking — all without a build step.
6
+ > See [COMPONENT_PATTERNS.md](./COMPONENT_PATTERNS.md) for component authoring.
7
+
8
+ ---
9
+
10
+ ## How It Works
11
+
12
+ TypeScript's `tsc` compiler validates JSDoc annotations via `--checkJs`,
13
+ giving us compile-time type checking without a build step.
14
+
15
+ A `jsconfig.json` at the project root enables `checkJs: true`. Running
16
+ `npm run typecheck` invokes `tsc --project jsconfig.json` which:
17
+
18
+ 1. Reads all `.js` files in `src/` and `scripts/`
19
+ 2. Parses JSDoc annotations as type information
20
+ 3. Reports type errors exactly like TypeScript would
21
+ 4. Emits nothing — `noEmit: true`
22
+
23
+ This means `@typedef`, `@type`, `@param`, and `@returns` are not just
24
+ documentation — they are **enforced types**.
25
+
26
+ ---
27
+
28
+ ## Component Properties
29
+
30
+ ```javascript
31
+ /**
32
+ * @typedef {Object} AppButtonHost
33
+ * @property {string} label - Button display text
34
+ * @property {'primary'|'secondary'|'ghost'} variant - Visual style
35
+ * @property {boolean} disabled - Disabled state
36
+ */
37
+
38
+ /** @type {import('hybrids').Component<AppButtonHost>} */
39
+ export default define({
40
+ tag: 'app-button',
41
+ label: '',
42
+ variant: 'primary',
43
+ disabled: false,
44
+ render: ({ label, variant, disabled }) => html`
45
+ <button class="${variant}" disabled="${disabled}">${label}</button>
46
+ `,
47
+ });
48
+ ```
49
+
50
+ ## Store Models
51
+
52
+ ```javascript
53
+ /**
54
+ * @typedef {Object} User
55
+ * @property {string} id - Unique identifier
56
+ * @property {string} firstName
57
+ * @property {string} lastName
58
+ * @property {string} email
59
+ */
60
+
61
+ /** @type {import('hybrids').Model<User>} */
62
+ const UserModel = { id: true, firstName: '', lastName: '', email: '' };
63
+ ```
64
+
65
+ ## Event Handlers
66
+
67
+ ```javascript
68
+ /**
69
+ * Increment the counter on the host element.
70
+ * @param {AppCounterHost & HTMLElement} host
71
+ * @param {MouseEvent} event
72
+ */
73
+ function handleClick(host, event) {
74
+ host.count++;
75
+ }
76
+ ```
77
+
78
+ ## Rules
79
+
80
+ - Every exported component gets a `@typedef` for its host interface.
81
+ - Every store model gets a `@typedef` for its shape.
82
+ - Event handlers document `host` and `event` param types.
83
+ - Keep JSDoc blocks to 3–5 lines. No novels.
84
+ - Use `/** @type {any} */ (expr)` for framework type limitations (e.g.
85
+ `store.pending()` on array results) — document why with a comment.
86
+ - Run `npm run typecheck` before committing. Zero errors required.
@@ -0,0 +1,190 @@
1
+ # Quickstart
2
+
3
+ Get a spec-compliant project running, develop against it, and keep it in sync as the spec evolves.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js ≥ 20
8
+ - npm ≥ 10
9
+
10
+ ## 1. Scaffold a New Project
11
+
12
+ ```bash
13
+ npx clearstack init
14
+ ```
15
+
16
+ The interactive prompt asks for:
17
+
18
+ | Prompt | Default | Notes |
19
+ |---|---|---|
20
+ | Project name | `my-app` | Creates a directory with this name |
21
+ | Description | `A Clearstack project` | Goes into package.json |
22
+ | Mode | — | **Fullstack**: Express + WebSocket + JSON DB + SSE. **Static**: localStorage only, no server |
23
+ | Port | `3000` | Fullstack only. Set in `.env` |
24
+ | Include examples? | Yes | Starter components demonstrating spec patterns |
25
+
26
+ This generates a complete project directory:
27
+
28
+ ```
29
+ my-app/
30
+ ├── .configs/ # eslint, prettier, jsconfig, web-test-runner
31
+ ├── .github/ # CI workflow, PR + issue templates
32
+ ├── docs/ # Spec docs (upstream-managed)
33
+ │ ├── clearstack/ # Clearstack spec docs (synced on update)
34
+ │ └── app-spec/ # Your project-specific specs (never overwritten)
35
+ ├── public/ # Static assets, index.html, import map
36
+ ├── scripts/ # vendor-deps, build-icons, spec checker
37
+ ├── src/
38
+ │ ├── components/ # atoms/, molecules/, organisms/, pages/
39
+ │ ├── store/ # Hybrids store models
40
+ │ ├── styles/ # Global CSS with native nesting
41
+ │ ├── router/ # Client-side routing
42
+ │ └── utils/ # Shared helpers
43
+ ├── tests/ # Node + browser tests
44
+ ├── data/ # JSON DB (fullstack only)
45
+ ├── src/server.js # Express server (fullstack only)
46
+ ├── .env # PORT, spec thresholds
47
+ └── package.json
48
+ ```
49
+
50
+ ## 2. Install and Run
51
+
52
+ ```bash
53
+ cd my-app
54
+ npm install
55
+ ```
56
+
57
+ `postinstall` automatically runs `vendor-deps.js` (copies hybrids to `public/vendor/`) and `build-icons.js` (extracts Lucide SVGs to `public/icons.json`).
58
+
59
+ ### Fullstack mode
60
+
61
+ ```bash
62
+ npm run dev # node --watch src/server.js
63
+ # → http://localhost:3000
64
+ ```
65
+
66
+ ### Static mode
67
+
68
+ ```bash
69
+ npx serve public # or any static file server
70
+ ```
71
+
72
+ ## 3. Development Workflow
73
+
74
+ ### Create a component
75
+
76
+ Every component is a plain ES module that exports a Hybrids descriptor. Place it in the appropriate atomic design tier:
77
+
78
+ ```
79
+ src/components/atoms/ # buttons, icons, badges
80
+ src/components/molecules/ # form fields, cards
81
+ src/components/organisms/ # lists, editors, canvases
82
+ src/components/pages/ # route-level views
83
+ ```
84
+
85
+ Register it in `src/components/index.js` and add a `<script>` or import map entry in `public/index.html` if needed.
86
+
87
+ ### Key rules while coding
88
+
89
+ - **≤150 lines per `.js` / `.css` file.** Add `// SPLIT CANDIDATE:` at 120 lines. When you hit the limit, extract a module.
90
+ - **Light DOM by default.** No `shadowRoot`. Shared styles in `src/styles/` apply everywhere.
91
+ - **JSDoc for types.** `@typedef`, `@param`, `@returns` — validated by `tsc --checkJs`.
92
+ - **No build step.** Every file runs as-is in the browser via ES modules and import maps.
93
+
94
+ ### Run checks during development
95
+
96
+ ```bash
97
+ npm run lint:fix # ESLint auto-fix
98
+ npm run format # Prettier auto-format
99
+ npm run typecheck # JSDoc type validation
100
+ npm test # Node + browser tests
101
+ npm run spec # Full interactive spec compliance check
102
+ ```
103
+
104
+ Or run individual spec checks:
105
+
106
+ ```bash
107
+ npm run spec:code # Code files ≤150 lines
108
+ npm run spec:docs # Doc files ≤500 lines
109
+ ```
110
+
111
+ ## 4. Project-Specific Specs
112
+
113
+ The `docs/app-spec/` directory is yours. Upstream updates never touch it. Use it for:
114
+
115
+ - Entity schemas and relationships
116
+ - Project-specific patterns or conventions
117
+ - API documentation beyond the base spec
118
+ - Architecture decisions (ADRs)
119
+ - Deviations from the spec (with rationale)
120
+
121
+ See [docs/app-spec/README.md](./app-spec/README.md) for the full guide.
122
+
123
+ ## 5. Update Spec Docs
124
+
125
+ When the spec evolves upstream, pull the latest docs into your project:
126
+
127
+ ```bash
128
+ npx clearstack update
129
+ ```
130
+
131
+ This:
132
+ - Copies updated spec docs from the package into your `docs/clearstack/` directory
133
+ - Syncs `.configs/` to latest standards
134
+ - Skips `docs/app-spec/` entirely — your project-specific specs are safe
135
+ - Writes a `.specversion` file so you can track which version you're on
136
+ - Prints which files changed so you can review with `git diff docs/ .configs/`
137
+
138
+ Review the diff, adjust your code if needed, then commit.
139
+
140
+ ## 6. Check Spec Compliance
141
+
142
+ Run the full compliance suite at any time:
143
+
144
+ ```bash
145
+ npx clearstack check
146
+ ```
147
+
148
+ This runs from the scaffolder package itself (no local scripts needed). It checks:
149
+
150
+ 1. **Code line counts** — all `.js` / `.css` files ≤150 lines
151
+ 2. **Doc line counts** — all `.md` files ≤500 lines
152
+ 3. **ESLint** — linting with the spec's config
153
+ 4. **Prettier** — formatting with the spec's config
154
+ 5. **JSDoc types** — `tsc --checkJs` against jsconfig
155
+
156
+ The same checks run in CI via the GitHub Actions workflow scaffolded into `.github/`.
157
+
158
+ ### Configuring thresholds
159
+
160
+ Override defaults in `.env`:
161
+
162
+ ```bash
163
+ SPEC_CODE_MAX_LINES=150
164
+ SPEC_DOCS_MAX_LINES=500
165
+ SPEC_CODE_EXTENSIONS=.js,.css
166
+ SPEC_DOCS_EXTENSIONS=.md
167
+ SPEC_IGNORE_DIRS=node_modules,public/vendor,.git,.configs
168
+ ```
169
+
170
+ ## 7. CI Pipeline
171
+
172
+ The scaffolded `.github/workflows/` runs all spec checks on every PR. A PR cannot merge unless all checks pass. The workflow runs:
173
+
174
+ ```
175
+ npm run spec:code → npm run spec:docs → npm run lint → npm run format → npm run typecheck → npm test
176
+ ```
177
+
178
+ ## Summary
179
+
180
+ | Task | Command |
181
+ |---|---|
182
+ | Scaffold a project | `npx clearstack init` |
183
+ | Install dependencies | `npm install` |
184
+ | Start dev server | `npm run dev` (fullstack) / `npx serve public` (static) |
185
+ | Lint + format | `npm run lint:fix && npm run format` |
186
+ | Type check | `npm run typecheck` |
187
+ | Run tests | `npm test` |
188
+ | Full spec check | `npm run spec` or `npx clearstack check` |
189
+ | Update spec docs | `npx clearstack update` |
190
+ | Review spec changes | `git diff docs/ .configs/` |
@@ -0,0 +1,163 @@
1
+ # Server & Dependencies
2
+ ## Express Server, Import Maps & Vendor Loading
3
+
4
+ > How the backend serves the frontend and how dependencies are resolved
5
+ > without a build step.
6
+ > See [BACKEND_API_SPEC.md](./BACKEND_API_SPEC.md) for the REST API contract.
7
+
8
+ ---
9
+
10
+ ## Express Server
11
+
12
+ `src/server.js` is a minimal Express app that serves static files and the API.
13
+
14
+ ### Responsibilities
15
+
16
+ | Route | Serves |
17
+ |---|---|
18
+ | `/` | `public/index.html` (app shell) |
19
+ | `/vendor/*` | `public/vendor/` (vendored ES modules) |
20
+ | `/src/*` | `src/` (application source, as-is) |
21
+ | `/api/*` | REST endpoints (see BACKEND_API_SPEC) |
22
+ | `/api/events` | SSE stream for realtime sync |
23
+
24
+ ### Key Rules
25
+
26
+ - **No middleware transforms.** Files are served byte-for-byte.
27
+ - **Correct MIME types.** `.js` files must be served as `application/javascript`.
28
+ - **No templating engine.** The HTML shell is a static file.
29
+ - **CORS not needed** — frontend and API share the same origin.
30
+
31
+ ### src/server.js Structure
32
+
33
+ ```javascript
34
+ import express from 'express';
35
+
36
+ const app = express();
37
+ const PORT = process.env.PORT || 3000;
38
+
39
+ // Static: vendored deps and app shell
40
+ app.use(express.static('public'));
41
+
42
+ // Static: application source (ES modules served directly)
43
+ app.use('/src', express.static('src'));
44
+
45
+ // API routes
46
+ // (see BACKEND_API_SPEC.md for full contract)
47
+ app.use(express.json());
48
+
49
+ // ... mount API routes here ...
50
+
51
+ app.listen(PORT, () => console.log(`http://localhost:${PORT}`));
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Vendor Dependency Loading
57
+
58
+ Third-party ES module packages are copied from `node_modules/` into
59
+ `public/vendor/` at install time. This makes them servable as static files.
60
+
61
+ ### scripts/vendor-deps.js
62
+
63
+ ```javascript
64
+ import { cpSync, mkdirSync } from 'node:fs';
65
+ import { resolve } from 'node:path';
66
+
67
+ const VENDOR_DIR = resolve('public/vendor');
68
+ const DEPS = [
69
+ { name: 'hybrids', src: 'node_modules/hybrids/src' },
70
+ ];
71
+
72
+ mkdirSync(VENDOR_DIR, { recursive: true });
73
+
74
+ for (const dep of DEPS) {
75
+ const dest = resolve(VENDOR_DIR, dep.name);
76
+ cpSync(dep.src, dest, { recursive: true });
77
+ console.log(`Vendored: ${dep.name} → ${dest}`);
78
+ }
79
+ ```
80
+
81
+ ### Wiring
82
+
83
+ In `package.json`:
84
+
85
+ ```json
86
+ {
87
+ "scripts": {
88
+ "postinstall": "node scripts/vendor-deps.js"
89
+ }
90
+ }
91
+ ```
92
+
93
+ Running `npm install` automatically vendors dependencies. The `public/vendor/`
94
+ directory should be in `.gitignore`.
95
+
96
+ ### Adding a New Dependency
97
+
98
+ 1. `npm install <package>`
99
+ 2. Add an entry to the `DEPS` array in `scripts/vendor-deps.js`
100
+ 3. Add a mapping in the import map (see below)
101
+ 4. Run `npm run postinstall` (or re-run `npm install`)
102
+
103
+ ---
104
+
105
+ ## Import Map
106
+
107
+ The browser resolves bare specifiers like `'hybrids'` via an import map
108
+ declared in `public/index.html`.
109
+
110
+ ### public/index.html
111
+
112
+ ```html
113
+ <!DOCTYPE html>
114
+ <html lang="en">
115
+ <head>
116
+ <meta charset="UTF-8">
117
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
118
+ <title>App</title>
119
+ <link rel="stylesheet" href="/src/styles/reset.css">
120
+ <link rel="stylesheet" href="/src/styles/tokens.css">
121
+
122
+ <script type="importmap">
123
+ {
124
+ "imports": {
125
+ "hybrids": "/vendor/hybrids/index.js"
126
+ }
127
+ }
128
+ </script>
129
+ </head>
130
+ <body>
131
+ <app-router></app-router>
132
+ <script type="module" src="/src/router/index.js"></script>
133
+ </body>
134
+ </html>
135
+ ```
136
+
137
+ ### How It Works
138
+
139
+ 1. Browser encounters `import { html } from 'hybrids'` in any ES module.
140
+ 2. Import map resolves `'hybrids'` → `/vendor/hybrids/index.js`.
141
+ 3. Server serves the file from `public/vendor/hybrids/index.js`.
142
+ 4. Hybrids' internal imports use relative paths — they resolve naturally.
143
+
144
+ ### Rules
145
+
146
+ - **One import map per page.** It must be declared before any `<script type="module">`.
147
+ - **No dynamic import map generation.** The map is static HTML.
148
+ - **Version pinning** is handled by `package-lock.json` + the vendor copy.
149
+ The vendored files always match the installed version.
150
+
151
+ ### Cache Busting
152
+
153
+ For production, append a version query param to the import map entries:
154
+
155
+ ```json
156
+ {
157
+ "imports": {
158
+ "hybrids": "/vendor/hybrids/index.js?v=9.1.22"
159
+ }
160
+ }
161
+ ```
162
+
163
+ Or use versioned directory names: `/vendor/hybrids@9.1.22/index.js`.