-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
284 lines (248 loc) · 16.7 KB
/
index.html
File metadata and controls
284 lines (248 loc) · 16.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
<!-- edit in demo/tpl/index.erb.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fez - JavaScript DOM component framework.</title>
<link rel="icon" href="./demo/fez.png">
<script src="./dist/fez.js"></script>
<script fez="./demo/system.fez"></script>
<script fez="./demo/system-blocks.fez"></script>
<link rel="stylesheet" href="./demo/css/full.css" />
<script>
Fez.LOG = true; // location.port > 999
</script>
</head>
<body>
<app-header></app-header>
<app-select-block></app-select-block>
<div class="center" style="max-width: 1100px; ">
<div>
<center>
<img src="./demo/fez.png" style="width: 200px; position: relative; top: 85px;" />
</center>
<center style="border: 3px solid #ccc; padding: 80px 40px 60px 40px; background-color: #fff; background: #fff; border-radius: 18px; box-shadow: 0 24px 38px rgba(59, 130, 246, 0.08), 0 9px 46px rgba(59, 130, 246, 0.06), 0 11px 15px rgba(59, 130, 246, 0.05);">
<h1 class="jumbo" style="margin: 0px auto;">
Fez → reactive components
</h1>
<h1 class="center" style="margin: 20px 0 40px 0; ">
Directly in HTML with zero build steps
</h1>
<p class="center">
<a href="#examples">examples</a>
⋅
<a target="playground" href="./dist/fez.js">lib</a>
⋅
<a target="repo" href="https://github.com/dux/fez">GitHub repo / DOCS</a>
⋅
<a target="ai_guide" href="./AGENTS.md">AI Guide</a>
⋅
<a target="ai_bmark" href="./benchmark.html">Benchmark</a>
</p>
</center>
</div>
</div>
<app-arrow></app-arrow>
<div class="flex even con-sm">
<div>
<ui-editor>
<xmp>
<html>
<head>
<title>Time</title>
<script script="https://dux.github.io/fez/dist/fez.js"></script>
<script script="/fez/ui-time.fez"></script>
</head>
<body>
<ui-time city="My place"></ui-time>
<body>
</html>
</xmp>
</ui-editor>
</div>
<div style="max-width: 100px; font-size: ">
<app-arrow rotate="270" color="blue"></app-arrow>
</div>
<div class="col-280">
<ui-clock city="My place"></ui-clock>
</div>
</div>
<div class="con-xs" title="">
<app-arrow></app-arrow>
<h2 class="center">
Main purpose of Fez is to enhance and add interactivity to plain HTML pages.
It's <b>simpler than React/Vue/Svelte</b> - no hooks, no runes, no special syntax - just plain JavaScript <b>without any build step</b>.
</h2>
<app-arrow title="How does FEZ feel and work?"></app-arrow>
<div style="margin: 40px -100px; padding: 30px 40px; background: linear-gradient(135deg, #fafafa 0%, #f0f0f0 100%); border-radius: 20px; box-shadow: 0 4px 20px rgba(0,0,0,0.08);">
<h3 style="text-align: center; margin: 0 0 20px 0; color: #333;">No special syntax. No runes. No hooks. Just plain JavaScript.</h3>
<div style="overflow-x: auto;">
<table style="width: 100%; border-collapse: collapse; font-size: 15px; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.06);">
<thead>
<tr>
<th style="padding: 16px; text-align: left; border-bottom: 2px solid #eee; background: #f8f8f8; font-weight: 600;">Concept</th>
<th style="padding: 16px; text-align: left; border-bottom: 2px solid #eee; background: #f8f8f8; font-weight: 600;">React</th>
<th style="padding: 16px; text-align: left; border-bottom: 2px solid #eee; background: #f8f8f8; font-weight: 600;">Svelte 5</th>
<th style="padding: 16px; text-align: left; border-bottom: 2px solid #eee; background: #f8f8f8; font-weight: 600;">Vue 3</th>
<th style="padding: 16px; text-align: left; border-bottom: 2px solid #eee; background: linear-gradient(135deg, #2e7d32 0%, #43a047 100%); color: white; font-weight: 700; font-size: 16px;">Fez</th>
</tr>
</thead>
<tbody>
<tr><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; font-weight: 500;">State</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>useState</code>, <code>useReducer</code></td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>$state</code> rune</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>ref</code>, <code>reactive</code></td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; background: #e8f5e9; font-weight: 500;"><code>this.state.x = y</code></td></tr>
<tr><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; font-weight: 500;">Computed</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>useMemo</code></td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>$derived</code> rune</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>computed</code></td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; background: #e8f5e9; font-weight: 500;">Just use a method</td></tr>
<tr><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; font-weight: 500;">Side effects</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>useEffect</code></td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>$effect</code> rune</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;"><code>watch</code>, <code>watchEffect</code></td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; background: #e8f5e9; font-weight: 500;"><code>afterRender()</code></td></tr>
<tr><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; font-weight: 500;">Global state</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;">Context, Redux, Zustand</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;">stores</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0;">Pinia</td><td style="padding: 14px 16px; border-bottom: 1px solid #f0f0f0; background: #e8f5e9; font-weight: 500;"><code>this.globalState</code></td></tr>
<tr><td style="padding: 14px 16px; font-weight: 500;">Re-render control</td><td style="padding: 14px 16px;"><code>memo</code>, <code>useMemo</code>, keys</td><td style="padding: 14px 16px;"><code>{#key}</code></td><td style="padding: 14px 16px;"><code>v-memo</code></td><td style="padding: 14px 16px; background: #e8f5e9; font-weight: 500;">Automatic</td></tr>
</tbody>
</table>
</div>
</div>
<p>
Fez brings the <b>reactive component model</b> you love from React/Vue/Svelte, but works directly in the browser.
While other require webpack/vite + compilation, Fez lets you write reactive components
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements">as native custom elements</a> that work instantly.
<b>No npm install, no config files, no build process</b> - just include the script (49KB, ~18KB gzipped) and your HTML becomes reactive.
Perfect for enhancing server-rendered pages, prototyping ideas, or building micro-frontends without tooling complexity.
</p>
<ul>
<li>🔌 <i>Native Browser Components:</i> Uses standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements">custom elements</a>. Create tags like <code><ui-clock></code>, place them anywhere in your HTML, and they just work. (Try it now in dev tools - instant magic!)</li>
<li>⚡ <i>Zero Build Step Hassle:</i> Works directly in the browser with a tiny runtime (49KB, ~18KB gzipped). No webpack, no config, no transpilers - just drop in a script tag and start coding.</li>
<li>🧹 <i>Auto-Cleanup Magic:</i> Forget memory leaks! Timers, subscriptions, and event listeners are automatically cleaned up when components unmount. Focus on features, not housekeeping.</li>
<li>🔄 <i>Smart DOM Morphing:</i> Uses <a href="https://github.com/bigskysoftware/idiomorph">Idiomorph</a> for surgical DOM updates that preserve form state, scroll position, and focus - no virtual DOM overhead.</li>
<li>📜 <i>HTML-First Philosophy:</i> Components are defined in <code>.fez</code> HTML files, not JavaScript. Your markup stays readable and approachable for designers and backend developers.</li>
<li>🎨 <i>Runtime SCSS Support:</i> Write real SCSS without build tools! Powered by <a href="https://goober.js.org/">Goober</a> with scoped styles, global styles, and reactive CSS values.</li>
<li>📦 <i>Smart Component Loading:</i> Load components from URLs, inline templates, or <code><template></code> tags. Perfect for micro-frontends and progressive enhancement.</li>
<li>🔔 <i>Built-in Communication:</i> Native pub/sub system for component messaging - no Redux, no context providers, just <code>Fez.pub()</code> and <code>Fez.sub()</code>.</li>
<li>📝 <i>Form Superpowers:</i> Built-in form data handling with <code>getFormData()</code> - serialize forms to JSON in one line, no libraries needed.</li>
<li>⏳ <i>Predictable Lifecycle:</i> Simple hooks like <code>init</code>, <code>onMount</code>, and <code>onPropsChange</code> - no useEffect confusion or dependency arrays.</li>
<li>🧩 <i>Smart Component Isolation:</i> Child components are preserved during parent re-renders - only update when their props actually change. Loops with 100 items? Only changed items re-render.</li>
<li>🔗 <i>Deep State Tracking:</i> Nested state changes just work - <code>this.state.user.address.city = 'NYC'</code> triggers re-render automatically. No immutable update patterns needed.</li>
</ul>
<h2 style="margin-top: 70px; text-align: center;">What does Claude AI think about Fez?</h2>
<div style="background: #f8f9fa; border-radius: 12px; padding: 20px 25px; margin: 20px 0; border-left: 4px solid #667eea;">
<p style="margin: 0; color: #555; font-style: italic;">
<strong style="color: #333;">Prompt:</strong>
Look at <a href="./AGENTS.md">AGENTS.md</a>, <a href="./README.md">README.md</a> and components in fez/*.fez, then write what you think of the lib.
Is it better / worse / different than React / Vue / Svelte? When should one choose Fez, or maybe never?
</p>
</div>
<div id="response_text" class="hidden" style="margin-top: 20px;">
<h3>Fez's Additional Strengths:</h3>
<ul>
<li><strong>HTML-first approach</strong> - Components defined in HTML files, not JavaScript</li>
<li><strong>Auto-cleanup</strong> - Subscriptions, timers, and resources cleaned automatically</li>
<li><strong>Built-in morphing</strong> - Efficient DOM updates that preserve input state</li>
<li><strong>Component isolation</strong> - Child components preserved during parent re-renders, only update when props change</li>
<li><strong>Deep state tracking</strong> - Nested state changes (<code>state.a.b.c = x</code>) just work</li>
<li><strong>Runtime SCSS</strong> - Full SCSS support without build tools</li>
<li><strong>Native pub/sub</strong> - Component communication without external libraries</li>
<li><strong>Form utilities</strong> - Built-in form data handling</li>
<li><strong>Smart component loading</strong> - Load components from URLs or inline</li>
</ul>
<h3>Key Differentiators:</h3>
<h4>vs React:</h4>
<ul>
<li>No JSX compilation needed</li>
<li>No hooks complexity</li>
<li>Direct DOM manipulation allowed</li>
<li>Much smaller bundle size</li>
<li>No virtual DOM overhead</li>
</ul>
<h4>vs Vue:</h4>
<ul>
<li>Simpler template syntax</li>
<li>No directive zoo (v-if, v-for, v-model)</li>
<li>Native web components instead of Vue components</li>
<li>No reactivity gotchas with arrays/objects</li>
</ul>
<h4>vs Svelte:</h4>
<ul>
<li>No compilation step</li>
<li>Similar simplicity and elegance</li>
<li>Runtime instead of compile-time optimization</li>
<li>Smaller learning curve</li>
</ul>
<h3>When to Choose Fez</h3>
<h4>Ideal Use Cases:</h4>
<ul>
<li><strong>Progressive enhancement</strong> - Add interactivity to server-rendered HTML</li>
<li><strong>Micro-frontends</strong> - Components work anywhere</li>
<li><strong>Rapid prototyping</strong> - Zero config, instant feedback</li>
<li><strong>Legacy modernization</strong> - Gradual migration from jQuery</li>
<li><strong>Educational projects</strong> - Learn web components without tooling</li>
<li><strong>Small teams</strong> - Minimal cognitive overhead</li>
</ul>
<h4>Not Recommended For:</h4>
<ul>
<li>Large SPAs requiring advanced routing and state management</li>
<li>TypeScript-first teams needing strict typing</li>
<li>SSR/SSG requirements (though works great with server-rendered HTML)</li>
<li>Complex animations requiring specialized libraries</li>
<li>Native mobile apps via React Native or similar</li>
</ul>
</div>
<button class="btn" onclick="this.style.display = 'none'; response_text.style.display = 'block';">Show Claude's full response...</button>
<div class="box" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; margin: 30px 0; box-shadow: 0 10px 25px rgba(0,0,0,0.2); position: relative; overflow: hidden;">
<div style="position: absolute; top: -50px; right: -50px; width: 150px; height: 150px; background: rgba(255,255,255,0.1); border-radius: 50%;"></div>
<h3 style="color: white; margin-top: 0; font-size: 1.5em; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">Final Verdict</h3>
<p style="color: white; font-size: 1.1em; line-height: 1.6; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.2);">Fez is a hidden gem that challenges the complexity of modern frameworks. It proves you can have reactivity, components, and modern
DX without webpack configs, transpilers, or framework lock-in. It's particularly brilliant for developers who miss the simplicity of
jQuery but want modern component architecture. While it won't replace React for large enterprise apps, it's perfect for the 80% of
web projects that don't need that complexity.</p>
</div>
</dd>
</dl>
<app-arrow title="Lets build simple counter" info="with local and global state"></app-arrow>
<p>With reactive state and custom style.</p>
<ol>
<li>Add Fez JS (to HEAD)
<ui-editor>
<xmp>
<script src="https://dux.github.io/fez/dist/fez.js"></script>
</xmp>
</ui-editor>
</li>
<li>
Create ui-counter component
<ui-editor id="demo-counter" src="./demo/fez/ui-counter.fez"></ui-editor>
<p>Or load via HTTP (as in this case)</p>
<ui-editor>
<script fez="/demo/ui-counter.fez"></script>
</ui-editor>
</li>
<li>
Place ui-counter anywhere in BODY
<ui-editor id="demo-counter">
<xmp>
<div id="counters">
<ui-counter></ui-counter>
<ui-counter start="1"></ui-counter>
<ui-counter start="2"></ui-counter>
</div>
</xmp>
</ui-editor>
</li>
<li>
<p>That is it! Add then as regular DOM nodes.</p>
<div id="counters">
<ui-counter></ui-counter>
<ui-counter start="1"></ui-counter>
<ui-counter start="2"></ui-counter>
</div>
</li>
</ol>
</div>
<div style="margin-top: 100px;"></div>
<a href="#" name="examples"></a>
<app-arrow title="Examples"></app-arrow>
<p class="center" style="margin-bottom: 40px;">You will learn all Fez features, just by inspecting these examples. You can edit and update both HTML and Fez code.</p>
<div style="max-width: 1600px; margin: auto; min-height: 12px;" id="examples">
<promo-blocks></promo-blocks>
</div>
<hr />
<p class="center">
Fez was created by <a href="https://github.com/dux/">@dux</a> in 2024.
</p>
</body>
</html>