@inglorious/web 2.2.2 → 2.2.3

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 (2) hide show
  1. package/README.md +352 -11
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,20 +1,237 @@
1
1
  # @inglorious/web
2
2
 
3
- [![NPM version](https://img.shields.io/npm/v/@inglorious/web.svg)](https://www.npmjs.com/package/@inglorious/web)
3
+ [![NPM version](https://img.shields.io/npm/v/@inglorious/web.svg)](https://www.npmjs.com/package/@inglorious/web)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- A lightweight web framework that combines the entity-based state management of **@inglorious/store** with the performance and simplicity of **lit-html**.
6
+ A lightweight, reactive-enough web framework built on **pure JavaScript**, the entity-based state management provided by **@inglorious/store**, and the DOM-diffing efficiency of **lit-html**.
7
+
8
+ Unlike modern frameworks that invent their own languages or rely on signals, proxies, or compilers, **@inglorious/web embraces plain JavaScript** and a transparent architecture.
7
9
 
8
10
  ---
9
11
 
10
12
  ## Features
11
13
 
12
- - **Seamless Integration**: A simple `mount` function to connect your store, templates, and the DOM.
13
- - **Efficient Rendering**: Leverages the performance of `lit-html` for DOM updates.
14
- - **Entity-Based Rendering**: Includes a powerful `api.render(id)` helper to render individual entities based on their type.
15
- - **Convenient Re-exports**: Provides direct access to `lit-html`'s `html`, `svg`, and core directives.
16
- - **Client-Side Router**: A simple, entity-based router for single-page applications.
17
- - **Fully Typed**: Strong TypeScript support for a great developer experience.
14
+ - **Full-tree Re-rendering with DOM Diffing**
15
+ Your entire template tree re-renders on every state change, while **lit-html updates only the minimal DOM parts**.
16
+ No VDOM, no signals, no hidden dependencies.
17
+
18
+ - **Entity-Based Rendering Model**
19
+ Each entity type defines its own `render(entity, api)` method.
20
+ `api.render(id)` composes the UI by invoking the correct renderer for each entity.
21
+
22
+ - **Simple and Predictable API**
23
+ Zero magic, zero reactivity graphs, zero compiler.
24
+ Just JavaScript functions and store events.
25
+
26
+ - **Router, Forms, Tables, Virtual Lists**
27
+ High-level primitives built on the same predictable model.
28
+
29
+ - **Zero Component State**
30
+ All state lives in the store — never inside components.
31
+
32
+ - **No Signals, No Subscriptions, No Memory Leaks**
33
+ Because every render is triggered by the store, and lit-html handles the rest.
34
+
35
+ - **No compilation required**
36
+ Apps can run directly in the browser — no build/compile step is strictly necessary (though you may use bundlers or Vite for convenience in larger projects).
37
+
38
+ ---
39
+
40
+ ## Create App (scaffolding)
41
+
42
+ To help bootstrap projects quickly, there's an official scaffolding tool: **[`@inglorious/create-app`](https://www.npmjs.com/package/@inglorious/create-app)**. It generates opinionated boilerplates so you can start coding right away.
43
+
44
+ Available templates:
45
+
46
+ - **minimal** — plain HTML, CSS, and JS (no build step)
47
+ - **js** — Vite-based JavaScript project
48
+ - **ts** — Vite + TypeScript project
49
+
50
+ Use the scaffolder to create a starter app tailored to your workflow.
51
+
52
+ ---
53
+
54
+ ## Key Architectural Insight
55
+
56
+ ### ✨ **Inglorious Web re-renders the whole template tree on each state change.**
57
+
58
+ Thanks to lit-html’s optimized diffing, this is fast, predictable, and surprisingly efficient.
59
+
60
+ This means:
61
+
62
+ - **You do NOT need fine-grained reactivity**
63
+ - **You do NOT need selectors/signals/memos**
64
+ - **You do NOT track dependencies between UI fragments**
65
+ - **You cannot accidentally create memory leaks through subscriptions**
66
+
67
+ You get Svelte-like ergonomic simplicity, but with no compiler and no magic.
68
+
69
+ > “Re-render everything → let lit-html update only what changed.”
70
+
71
+ It's that simple — and surprisingly fast in practice.
72
+
73
+ ---
74
+
75
+ ## When to Use Inglorious Web
76
+
77
+ - You want predictable behavior
78
+ - You prefer explicit state transitions
79
+ - You want to avoid complex reactive graphs
80
+ - You want UI to be fully controlled by your entity-based store
81
+ - You want to stay entirely in **JavaScript**, without DSLs or compilers
82
+ - You want **React-like declarative UI** but without the cost and overhead of React
83
+
84
+ This framework is ideal for both small apps and large business UIs.
85
+
86
+ --
87
+
88
+ ## When NOT to Use Inglorious Web
89
+
90
+ - You need server-side rendering (SSR) or static site generation (SSG) - WIP
91
+ - You need fine-grained reactivity for very large datasets (1000+ items per view)
92
+ - You're building a library that needs to be framework-agnostic
93
+ - Your team is already deeply invested in React/Vue/Angular
94
+
95
+ ---
96
+
97
+ ## Why Inglorious Web Avoids Signals
98
+
99
+ Other modern frameworks use:
100
+
101
+ - Proxies (Vue)
102
+ - Observables (MobX)
103
+ - Fine-grained signals (Solid, Angular v17+)
104
+ - Compiler-generated reactivity (Svelte)
105
+ - Fiber or granular subscriptions (React, Preact, Qwik, etc.)
106
+
107
+ These systems are powerful but introduce:
108
+
109
+ - hidden dependencies
110
+ - memory retention risks
111
+ - unpredictable update ordering
112
+ - steep learning curves
113
+ - framework-specific languages
114
+ - need for cleanup, teardown, and special lifecycle APIs
115
+ - challenges when mixing with game engines, workers, or non-UI code
116
+
117
+ ### Inglorious Web takes a different stance:
118
+
119
+ ✔ **Every entity update is explicit**
120
+ ✔ **Every UI update is a full diff pass**
121
+ ✔ **Every part of the system is just JavaScript**
122
+ ✔ **No special lifecycle**
123
+ ✔ **No subscriptions needed**
124
+ ✔ **No signals**
125
+ ✔ **No cleanup**
126
+ ✔ **No surprises**
127
+
128
+ This makes it especially suitable for:
129
+
130
+ - realtime applications
131
+ - hybrid UI/game engine contexts
132
+ - large enterprise apps where predictability matters
133
+ - developers who prefer simplicity over magic
134
+
135
+ ---
136
+
137
+ # Comparison with Other Frameworks
138
+
139
+ Here’s how @inglorious/web compares to the major players:
140
+
141
+ ---
142
+
143
+ ## **React**
144
+
145
+ | Feature | React | Inglorious Web |
146
+ | ------------------------- | ----------------------------- | ---------------------------------- |
147
+ | Rendering model | VDOM diff + effects | Full tree template + lit-html diff |
148
+ | Language | JSX (non-JS) | Pure JavaScript |
149
+ | Component state | Yes | No — store only |
150
+ | Refs & lifecycles | Many | None needed |
151
+ | Signals / fine reactivity | No (but heavy reconciliation) | No (rely on lit-html diff) |
152
+ | Reconciliation overhead | High (full VDOM diff) | Low (template string diff) |
153
+ | Bundle size | Large | Tiny |
154
+ | Learning curve | Medium/High | Very low |
155
+
156
+ React is powerful but complicated. Inglorious Web is simpler, lighter, and closer to native JS.
157
+
158
+ ---
159
+
160
+ ## **Vue (3)**
161
+
162
+ | Feature | Vue | Inglorious Web |
163
+ | --------------- | -------------------------- | ----------------------------------- |
164
+ | Reactivity | Proxy-based, deep tracking | Event-based updates + lit-html diff |
165
+ | Templates | DSL | JavaScript templates |
166
+ | Component state | Yes | No |
167
+ | Lifecycle | Many | None |
168
+ | Compiler | Required for SFC | None |
169
+
170
+ Vue reactivity is elegant but complex. Inglorious Web avoids proxies and keeps everything explicit.
171
+
172
+ ---
173
+
174
+ ## **Svelte**
175
+
176
+ | Feature | Svelte | Inglorious Web |
177
+ | -------------- | --------------------------- | ------------------ |
178
+ | Compiler | Required | None |
179
+ | Reactivity | Compiler transforms $labels | Transparent JS |
180
+ | Granularity | Fine-grained | Full-tree rerender |
181
+ | Learning curve | Medium | Low |
182
+
183
+ Svelte is magic; Inglorious Web is explicit.
184
+
185
+ ---
186
+
187
+ ## **SolidJS**
188
+
189
+ | Feature | Solid | Inglorious Web |
190
+ | ---------- | -------------------- | ------------------ |
191
+ | Reactivity | Fine-grained signals | No signals |
192
+ | Components | Run once | Rerun always |
193
+ | Cleanup | Required | None |
194
+ | Behavior | Highly optimized | Highly predictable |
195
+
196
+ Solid is extremely fast but requires a mental model.
197
+ Inglorious Web trades peak performance for simplicity and zero overhead.
198
+
199
+ ---
200
+
201
+ ## **Qwik**
202
+
203
+ | Feature | Qwik | Inglorious Web |
204
+ | -------------------- | -------------------- | -------------- |
205
+ | Execution model | Resumable | Plain JS |
206
+ | Framework complexity | Very high | Very low |
207
+ | Reactivity | Fine-grained signals | None |
208
+
209
+ Qwik targets extreme performance at extreme complexity.
210
+ Inglorious Web is minimal, predictable, and tiny.
211
+
212
+ ---
213
+
214
+ ## **HTMX / Alpine / Vanilla DOM**
215
+
216
+ You are closer philosophically to **HTMX** and **vanilla JS**, but with a declarative rendering model and entity-based state.
217
+
218
+ ---
219
+
220
+ # Why Choose Inglorious Web
221
+
222
+ - Minimalistic
223
+ - Pure JavaScript
224
+ - Entity-based and predictable
225
+ - Extremely easy to reason about
226
+ - One render path, no hidden rules
227
+ - No reactivity graphs
228
+ - No per-component subscriptions
229
+ - No memory leaks
230
+ - No build step required (apps can run in the browser)
231
+ - Works perfectly in hybrid UI/game engine contexts
232
+ - Uses native ES modules and standards
233
+
234
+ If you want a framework that **does not fight JavaScript**, this is the one.
18
235
 
19
236
  ---
20
237
 
@@ -90,6 +307,57 @@ The `mount` function subscribes to the store and automatically re-renders your t
90
307
 
91
308
  ---
92
309
 
310
+ ## Redux DevTools Integration
311
+
312
+ `@inglorious/web` ships with first-class support for the **Redux DevTools Extension**, allowing you to:
313
+
314
+ - inspect all store events
315
+ - time-travel through state changes
316
+ - restore previous states
317
+ - debug your entity-based logic visually
318
+
319
+ To enable DevTools, add the middleware provided by `createDevtools()`.
320
+
321
+ ### 1. Create a `middlewares.js` file
322
+
323
+ ```javascript
324
+ // middlewares.js
325
+ import { createDevtools } from "@inglorious/web"
326
+
327
+ export const middlewares = []
328
+
329
+ // Enable DevTools only in development mode
330
+ if (import.meta.env.DEV) {
331
+ middlewares.push(createDevtools().middleware)
332
+ }
333
+ ```
334
+
335
+ ### 2. Pass middlewares when creating the store
336
+
337
+ ```javascript
338
+ // store.js
339
+ import { createStore } from "@inglorious/web"
340
+ import { middlewares } from "./middlewares.js"
341
+
342
+ export const store = createStore({
343
+ types,
344
+ entities,
345
+ middlewares,
346
+ })
347
+ ```
348
+
349
+ Now your application state is fully visible in the Redux DevTools browser extension.
350
+
351
+ ### What You’ll See in DevTools
352
+
353
+ - Each event you dispatch via `api.notify(event, payload)` will appear as an action in the DevTools timeline.
354
+ - The entire store is visible under the _State_ tab.
355
+ - You can time-travel or replay events exactly like in Redux.
356
+
357
+ No additional configuration is needed.
358
+
359
+ ---
360
+
93
361
  ## Client-Side Router
94
362
 
95
363
  `@inglorious/web` includes a lightweight, entity-based client-side router. It integrates directly into your `@inglorious/store` state, allowing your components to reactively update based on the current URL.
@@ -114,7 +382,7 @@ const types = {
114
382
  render: (entity, api) => {
115
383
  // Access route params from the router entity
116
384
  const { params } = api.getEntity("router")
117
- return html`<h1>User ${params.id} - ${entity.username}</h1>`
385
+ return html`<h1>User ${params?.id ?? "Unknown"} - ${entity.username}</h1>`
118
386
  },
119
387
  },
120
388
  notFoundPage: {
@@ -416,20 +684,93 @@ For convenience, `@inglorious/web` re-exports the most common utilities from `@i
416
684
 
417
685
  ```javascript
418
686
  import {
687
+ // from @inglorious/store
419
688
  createStore,
420
- creteDevtools,
689
+ createDevtools,
421
690
  createSelector,
691
+ // from lit-html
422
692
  mount,
423
693
  html,
424
- router,
425
694
  render,
426
695
  svg,
696
+ // lit-html directives
697
+ choose,
427
698
  classMap,
699
+ ref,
700
+ repeat,
701
+ styleMap,
702
+ when,
703
+ // router stuff
704
+ router,
705
+ // table stuff
706
+ table,
707
+ // form stuff
708
+ form,
709
+ getFieldError,
710
+ getFieldValue,
711
+ isFieldTouched,
712
+ // virtualized list stuff
713
+ list,
428
714
  } from "@inglorious/web"
429
715
  ```
430
716
 
431
717
  ---
432
718
 
719
+ ## Error Handling
720
+
721
+ When an entity's `render()` method throws an error, it can crash your entire app since the whole tree re-renders.
722
+
723
+ **Best practice:** Wrap your render logic in try-catch at the entity level:
724
+
725
+ ```javascript
726
+ const myType = {
727
+ render(entity, api) {
728
+ try {
729
+ // Your render logic
730
+ return html`<div>...</div>`
731
+ } catch (error) {
732
+ console.error("Render error:", error)
733
+ return html`<div class="error">Failed to render ${entity.id}</div>`
734
+ }
735
+ },
736
+ }
737
+ ```
738
+
739
+ ---
740
+
741
+ ## Performance Tips
742
+
743
+ 1. **Keep render() pure** - No side effects, no API calls
744
+ 2. **Avoid creating new objects in render** - Use entity properties, not inline `{}`
745
+ 3. **Use `repeat()` directive for lists** - Helps lit-html track item identity
746
+ 4. **Profile with browser DevTools** - Look for slow renders (>16ms)
747
+ 5. **Consider virtualization** - Use `list` type for 1000+ items
748
+
749
+ If renders are slow:
750
+
751
+ - Move expensive computations to event handlers
752
+ - Cache derived values on the entity
753
+ - ...Or memoize them!
754
+
755
+ ---
756
+
757
+ ## Relationship to Inglorious Engine
758
+
759
+ `@inglorious/web` shares its architectural philosophy with [Inglorious Engine](https://www.npmjs.com/package/@inglorious/engine):
760
+
761
+ - **Same state management** - Both use `@inglorious/store`
762
+ - **Same event system** - Entity behaviors respond to events
763
+ - **Same rendering model** - Full-state render on every update
764
+
765
+ The key difference:
766
+
767
+ - **@inglorious/engine** targets game loops (60fps, Canvas/WebGL rendering)
768
+ - **@inglorious/web** targets web UIs (DOM rendering, user interactions)
769
+
770
+ You can even mix them in the same app!
771
+
772
+ ---
773
+
433
774
  ## License
434
775
 
435
776
  **MIT License - Free and open source**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/web",
3
- "version": "2.2.2",
3
+ "version": "2.2.3",
4
4
  "description": "A new web framework that leverages the power of the Inglorious Store combined with the performance and simplicity of lit-html.",
5
5
  "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "lit-html": "^3.3.1",
41
41
  "@inglorious/utils": "3.7.0",
42
- "@inglorious/store": "7.1.1"
42
+ "@inglorious/store": "7.1.2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "prettier": "^3.6.2",