toiljs 0.0.15 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +13 -13
- package/.gitattributes +2 -2
- package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
- package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
- package/.github/ISSUE_TEMPLATE/config.yml +8 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
- package/.github/changelog-config.json +45 -45
- package/.github/dependabot.yml +27 -27
- package/.github/workflows/ci.yml +191 -191
- package/.prettierrc.json +11 -11
- package/.vscode/settings.json +9 -9
- package/CHANGELOG.md +116 -5
- package/LICENSE +187 -187
- package/README.md +524 -315
- package/as-pect.asconfig.json +34 -34
- package/as-pect.config.js +65 -65
- package/assets/logo.svg +36 -36
- package/build/backend/.tsbuildinfo +1 -1
- package/build/backend/index.d.ts +1 -0
- package/build/backend/index.js +20 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +1320 -696
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/dev/devtools.d.ts +6 -0
- package/build/client/dev/devtools.js +479 -0
- package/build/client/dev/error-overlay.d.ts +9 -0
- package/build/client/dev/error-overlay.js +19 -4
- package/build/client/errors.d.ts +1 -0
- package/build/client/errors.js +3 -0
- package/build/client/index.d.ts +2 -0
- package/build/client/index.js +2 -0
- package/build/client/navigation/prefetch.d.ts +1 -0
- package/build/client/navigation/prefetch.js +35 -0
- package/build/client/routing/Router.js +1 -1
- package/build/client/routing/hooks.js +6 -2
- package/build/client/routing/loader.d.ts +23 -0
- package/build/client/routing/loader.js +53 -7
- package/build/client/routing/mount.js +4 -3
- package/build/client/rpc.d.ts +1 -0
- package/build/client/rpc.js +37 -0
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/config.d.ts +16 -0
- package/build/compiler/config.js +9 -0
- package/build/compiler/docs.js +78 -21
- package/build/compiler/generate.js +5 -4
- package/build/compiler/index.d.ts +3 -2
- package/build/compiler/index.js +2 -2
- package/build/compiler/plugin.js +228 -0
- package/build/compiler/prerender.d.ts +1 -0
- package/build/compiler/prerender.js +1 -1
- package/build/compiler/seo.d.ts +1 -1
- package/build/compiler/seo.js +20 -5
- package/build/compiler/ssg.js +39 -2
- package/build/compiler/vite.js +25 -0
- package/build/io/.tsbuildinfo +1 -1
- package/build/io/codec.d.ts +54 -0
- package/build/io/codec.js +143 -0
- package/build/io/index.d.ts +1 -2
- package/build/io/index.js +1 -2
- package/build/logger/.tsbuildinfo +1 -1
- package/build/shared/.tsbuildinfo +1 -1
- package/eslint.config.js +48 -48
- package/examples/basic/client/404.tsx +11 -11
- package/examples/basic/client/components/.gitkeep +1 -1
- package/examples/basic/client/global-error.tsx +13 -13
- package/examples/basic/client/layout.tsx +25 -25
- package/examples/basic/client/public/images/.gitkeep +1 -1
- package/examples/basic/client/public/images/logo.svg +36 -36
- package/examples/basic/client/public/robots.txt +2 -2
- package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
- package/examples/basic/client/routes/features/error/error.tsx +16 -16
- package/examples/basic/client/routes/features/index.tsx +1 -1
- package/examples/basic/client/routes/features/template/b.tsx +14 -14
- package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
- package/examples/basic/client/routes/gallery/layout.tsx +13 -13
- package/examples/basic/client/routes/io.tsx +23 -24
- package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
- package/examples/basic/client/routes/rest.tsx +74 -0
- package/examples/basic/client/routes/rpc.tsx +43 -0
- package/examples/basic/client/routes/search.tsx +61 -61
- package/examples/basic/client/toil.tsx +5 -5
- package/package.json +167 -148
- package/presets/eslint.js +88 -88
- package/presets/no-uint8array-tostring.js +200 -200
- package/presets/prettier-plugin.js +51 -0
- package/presets/prettier.json +19 -18
- package/presets/tsconfig.json +37 -37
- package/server/runtime/README.md +97 -0
- package/server/runtime/abort/abort.ts +27 -0
- package/server/runtime/env/Server.ts +61 -0
- package/server/runtime/envelope.ts +191 -0
- package/server/runtime/exports/index.ts +52 -0
- package/server/runtime/handlers/ToilHandler.ts +34 -0
- package/server/runtime/index.ts +26 -0
- package/server/runtime/lang/Potential.ts +5 -0
- package/server/runtime/memory.ts +81 -0
- package/server/runtime/request.ts +55 -0
- package/server/runtime/response.ts +86 -0
- package/server/runtime/rest/Rest.ts +39 -0
- package/server/runtime/rest/RestHandler.ts +20 -0
- package/server/runtime/rest/RouteContext.ts +82 -0
- package/server/runtime/rest/match.ts +48 -0
- package/server/runtime/tsconfig.json +7 -0
- package/src/backend/index.ts +202 -160
- package/src/cli/create.ts +15 -5
- package/src/cli/diagnostics.ts +81 -0
- package/src/cli/doctor.ts +384 -7
- package/src/cli/index.ts +11 -2
- package/src/cli/proc.ts +50 -50
- package/src/cli/updates.ts +69 -69
- package/src/cli/validate.ts +31 -31
- package/src/client/channel/channel.ts +146 -146
- package/src/client/components/Form.tsx +65 -65
- package/src/client/components/Script.tsx +113 -113
- package/src/client/components/Slot.tsx +21 -21
- package/src/client/dev/devtools.tsx +1018 -0
- package/src/client/dev/error-overlay.tsx +30 -4
- package/src/client/errors.ts +11 -0
- package/src/client/head/head.ts +167 -167
- package/src/client/head/metadata.ts +112 -112
- package/src/client/index.ts +91 -89
- package/src/client/navigation/NavLink.tsx +86 -86
- package/src/client/navigation/navigation.ts +235 -235
- package/src/client/navigation/prefetch.ts +169 -130
- package/src/client/navigation/scroll.ts +53 -53
- package/src/client/routing/Router.tsx +8 -2
- package/src/client/routing/action.ts +122 -122
- package/src/client/routing/error-boundary.tsx +43 -43
- package/src/client/routing/hooks.ts +21 -6
- package/src/client/routing/loader.ts +325 -235
- package/src/client/routing/match.ts +47 -47
- package/src/client/routing/mount.tsx +54 -52
- package/src/client/routing/params-context.ts +10 -10
- package/src/client/routing/slot-context.ts +7 -7
- package/src/client/rpc.ts +64 -0
- package/src/client/search/search.ts +189 -189
- package/src/client/search/use-page-search.ts +73 -73
- package/src/client/types.ts +73 -73
- package/src/compiler/config.ts +221 -182
- package/src/compiler/docs.ts +285 -228
- package/src/compiler/generate.ts +395 -394
- package/src/compiler/index.ts +66 -57
- package/src/compiler/pages.ts +70 -70
- package/src/compiler/plugin.ts +258 -2
- package/src/compiler/prerender.ts +156 -156
- package/src/compiler/seo.ts +417 -390
- package/src/compiler/ssg.ts +171 -126
- package/src/compiler/vite.ts +34 -0
- package/src/io/FastMap.ts +151 -127
- package/src/io/FastSet.ts +15 -1
- package/src/io/codec.ts +217 -0
- package/src/io/index.ts +10 -11
- package/src/io/lengths.ts +14 -14
- package/src/io/types.ts +19 -18
- package/src/logger/index.ts +22 -22
- package/src/shared/index.ts +10 -10
- package/std/client/index.d.ts +15 -15
- package/std/client/package.json +3 -3
- package/test/assembly/example.spec.ts +17 -7
- package/test/channel.test.ts +21 -21
- package/test/doctor.test.ts +65 -0
- package/test/dom/Link.test.tsx +47 -47
- package/test/dom/NavLink.test.tsx +37 -37
- package/test/dom/error-overlay.test.tsx +44 -44
- package/test/dom/loader.test.tsx +121 -121
- package/test/dom/navigation.test.ts +59 -59
- package/test/dom/revalidate.test.tsx +38 -38
- package/test/dom/route-head.test.tsx +78 -78
- package/test/dom/router-loading.test.tsx +44 -44
- package/test/dom/scroll.test.ts +56 -56
- package/test/dom/use-metadata.test.tsx +58 -58
- package/test/errors.test.ts +21 -0
- package/test/io.test.ts +117 -93
- package/test/navlink.test.ts +28 -28
- package/test/placeholder.test.ts +9 -9
- package/test/prettier-plugin.test.ts +46 -0
- package/test/routes.test.ts +76 -76
- package/test/rpc.test.ts +50 -0
- package/test/seo.test.ts +175 -164
- package/test/slot-layouts.test.ts +69 -69
- package/test/ssg.test.ts +36 -36
- package/test/update.test.ts +44 -44
- package/test/validate.test.ts +42 -42
- package/tests/data-parity/generated-parity.ts +99 -0
- package/tests/data-parity/parity.ts +80 -0
- package/tests/data-parity/spec.ts +46 -0
- package/toil-routes.d.ts +7 -0
- package/tsconfig.backend.json +13 -13
- package/tsconfig.base.json +35 -35
- package/tsconfig.cli.json +13 -13
- package/tsconfig.client.json +14 -14
- package/tsconfig.compiler.json +13 -13
- package/tsconfig.io.json +12 -12
- package/tsconfig.json +22 -22
- package/tsconfig.logger.json +12 -12
- package/tsconfig.server.json +10 -10
- package/tsconfig.shared.json +12 -12
- package/vitest.config.ts +26 -26
- package/.idea/codeStyles/Project.xml +0 -54
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/prettier.xml +0 -7
- package/.idea/toiljs.iml +0 -8
- package/.idea/vcs.xml +0 -6
- package/.toil/entry.tsx +0 -9
- package/.toil/index.html +0 -12
- package/.toil/routes.ts +0 -9
- package/build/cli/configure.d.ts +0 -16
- package/build/cli/configure.js +0 -272
- package/build/cli/create.d.ts +0 -16
- package/build/cli/create.js +0 -420
- package/build/cli/diagnostics.d.ts +0 -55
- package/build/cli/diagnostics.js +0 -333
- package/build/cli/doctor.d.ts +0 -6
- package/build/cli/doctor.js +0 -249
- package/build/cli/features.d.ts +0 -25
- package/build/cli/features.js +0 -107
- package/build/cli/index.d.ts +0 -2
- package/build/cli/proc.d.ts +0 -6
- package/build/cli/proc.js +0 -31
- package/build/cli/ui.d.ts +0 -9
- package/build/cli/ui.js +0 -75
- package/build/cli/update.d.ts +0 -7
- package/build/cli/update.js +0 -117
- package/build/cli/updates.d.ts +0 -10
- package/build/cli/updates.js +0 -45
- package/build/cli/validate.d.ts +0 -4
- package/build/cli/validate.js +0 -19
- package/build/client/Link.d.ts +0 -8
- package/build/client/Link.js +0 -44
- package/build/client/NavLink.d.ts +0 -14
- package/build/client/NavLink.js +0 -37
- package/build/client/Router.d.ts +0 -7
- package/build/client/Router.js +0 -55
- package/build/client/channel.d.ts +0 -23
- package/build/client/channel.js +0 -94
- package/build/client/error-boundary.d.ts +0 -16
- package/build/client/error-boundary.js +0 -19
- package/build/client/head.d.ts +0 -26
- package/build/client/head.js +0 -87
- package/build/client/hooks.d.ts +0 -17
- package/build/client/hooks.js +0 -48
- package/build/client/lazy.d.ts +0 -16
- package/build/client/lazy.js +0 -53
- package/build/client/match.d.ts +0 -2
- package/build/client/match.js +0 -32
- package/build/client/mount.d.ts +0 -2
- package/build/client/mount.js +0 -13
- package/build/client/navigation.d.ts +0 -13
- package/build/client/navigation.js +0 -97
- package/build/client/params-context.d.ts +0 -2
- package/build/client/params-context.js +0 -2
- package/build/client/prefetch.d.ts +0 -11
- package/build/client/prefetch.js +0 -100
- package/build/client/runtime.d.ts +0 -31
- package/build/client/runtime.js +0 -112
- package/build/client/scroll.d.ts +0 -8
- package/build/client/scroll.js +0 -36
- package/build/io/BinaryReader.d.ts +0 -44
- package/build/io/BinaryReader.js +0 -244
- package/build/io/BinaryWriter.d.ts +0 -44
- package/build/io/BinaryWriter.js +0 -297
- package/build/server/release.wasm +0 -0
- package/build/server/release.wat +0 -9
- package/src/io/BinaryReader.ts +0 -340
- package/src/io/BinaryWriter.ts +0 -385
- package/src/server/index.ts +0 -10
- package/src/server/main.ts +0 -13
- package/src/server/tsconfig.json +0 -4
- package/toil-env.d.ts +0 -16
- package/toilconfig.json +0 -30
package/README.md
CHANGED
|
@@ -1,315 +1,524 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
<img src="https://raw.githubusercontent.com/dacely-cloud/toiljs/main/assets/logo.svg" alt="ToilJS" width="128" height="128" />
|
|
4
|
-
|
|
5
|
-
# ToilJS
|
|
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
|
-
toiljs start
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://raw.githubusercontent.com/dacely-cloud/toiljs/main/assets/logo.svg" alt="ToilJS" width="128" height="128" />
|
|
4
|
+
|
|
5
|
+
# ToilJS
|
|
6
|
+
|
|
7
|
+
### The fullstack React framework, built for hyperscale.
|
|
8
|
+
|
|
9
|
+
#### The first universal client and server framework.
|
|
10
|
+
|
|
11
|
+
<sub>Nothing to configure: routing, data, SEO, top-tier tooling, and full AI support, all built in.</sub>
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
**⚡ First-class WebTransport over HTTP/3**, with automatic WebSocket fallback.
|
|
16
|
+
|
|
17
|
+
<br/>
|
|
18
|
+
|
|
19
|
+
[](https://www.npmjs.com/package/toiljs)
|
|
20
|
+
[](https://www.typescriptlang.org/)
|
|
21
|
+
[](https://react.dev/)
|
|
22
|
+
[](#the-server-toilscript--webassembly)
|
|
23
|
+
[](#realtime)
|
|
24
|
+
[](./LICENSE)
|
|
25
|
+
|
|
26
|
+
<br/>
|
|
27
|
+
|
|
28
|
+
<img src="https://img.shields.io/badge/React_19-20232a?style=for-the-badge&logo=react&logoColor=61dafb" alt="React 19" />
|
|
29
|
+
<img src="https://img.shields.io/badge/TypeScript-3178c6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
30
|
+
<img src="https://img.shields.io/badge/Vite-646cff?style=for-the-badge&logo=vite&logoColor=white" alt="Vite" />
|
|
31
|
+
<img src="https://img.shields.io/badge/WebAssembly-654ff0?style=for-the-badge&logo=webassembly&logoColor=white" alt="WebAssembly" />
|
|
32
|
+
<img src="https://img.shields.io/badge/ToilScript-cb9820?style=for-the-badge&logoColor=white" alt="ToilScript" />
|
|
33
|
+
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
**ToilJS is a fullstack React framework built for hyperscale.** That is the whole point. Most React frameworks are built for convenience and start to buckle the moment real traffic arrives. Toil is built the other way around: for scale that serves the millionth request as easily as the first. Your client ships as a static bundle to the edge, and your server compiles to a single portable module designed to run at line rate, so the app you write on your laptop is shaped from day one to take serious load instead of folding under it.
|
|
39
|
+
|
|
40
|
+
And it is the entire stack, already wired and configured: routing, data, caching, SEO, site search, an image and font pipeline, realtime, a dev toolbar with AI, and a strict toolchain. One command scaffolds it, then you build your app, not your stack. Nothing to assemble, nothing to glue, nothing to configure.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx toiljs create my-app
|
|
44
|
+
cd my-app
|
|
45
|
+
npm run dev
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Drop a `.tsx` file in `client/routes/` and it is a route: typed, code-split, prefetched, with its data loaded before render. Your `server/` is written in **ToilScript** (TypeScript syntax) and compiles to a single WebAssembly module. You configured nothing.
|
|
49
|
+
|
|
50
|
+
<div align="center">
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
your app
|
|
54
|
+
┌──────────────────────┬──────────────────────┐
|
|
55
|
+
│ client/ │ server/ │
|
|
56
|
+
│ React + TSX │ ToilScript (.ts) │
|
|
57
|
+
│ static SPA bundle │ ──▶ WebAssembly │
|
|
58
|
+
└──────────┬───────────┴───────────┬───────────┘
|
|
59
|
+
│ │
|
|
60
|
+
CDN / static host WASM edge runtime
|
|
61
|
+
(typed RPC between them)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
The client is fully static (host it anywhere). The server is a portable compiled module. The two are separated by design and joined by a typed contract, so the frontend can ship to a CDN while the backend runs wherever it is deployed.
|
|
67
|
+
|
|
68
|
+
## Built for scale
|
|
69
|
+
|
|
70
|
+
Toil's architecture is the scaling story. There is no monolith to keep warm and nothing re-rendering your pages on every request.
|
|
71
|
+
|
|
72
|
+
- **The client is static.** `build` emits a plain SPA bundle with each route's HTML already prerendered. It has no runtime server dependency, so it ships to any CDN or edge network and is cached and served close to every user.
|
|
73
|
+
- **The server is one portable module.** Your ToilScript backend compiles to a single self-contained module: no Node runtime to boot, no framework cold start, no per-request bootstrap. It is small, it starts instantly, and it runs the same everywhere.
|
|
74
|
+
- **Client and server are decoupled.** They are separate artifacts joined only by a typed contract, so the frontend scales as static files while the backend scales as stateless compute. Neither one bottlenecks the other.
|
|
75
|
+
- **Shaped for the edge.** That compiled module is exactly the unit a hyperscale edge runtime is built to serve: isolated per tenant, replicated across regions, run at line rate.
|
|
76
|
+
|
|
77
|
+
That is the platform Toil is being built toward. The architecture above ships today; this is the stack that runs it at planetary scale:
|
|
78
|
+
|
|
79
|
+
- **First-class WebTransport** *(coming)*: realtime over HTTP/3, multiplexed bidirectional streams and datagrams over QUIC with no head-of-line blocking. Toil is built to be the **first framework to ship first-class WebTransport**, and it falls back to WebSocket automatically, so the same channel API simply runs on the fastest transport available. WebSocket channels work today.
|
|
80
|
+
- **A purpose-built edge runtime** *(coming)*: your compiled server runs as an isolated tenant at line rate, replicated across regions, instead of on a general-purpose Node process.
|
|
81
|
+
- **ToilDB, edge-replicated typed data** *(coming)*: typed collections where the method name tells you the cost, local-fast reads, CRDT writes that merge everywhere, owner-routed writes, and rare global claims that are explicitly slow.
|
|
82
|
+
- **Post-quantum-ready transport** *(coming)*: forward-looking encryption as the QUIC layer lands.
|
|
83
|
+
- **Dacely Cloud** *(coming)*: managed hosting for the whole stack, push the app and the client goes to the edge while the server runs on the runtime.
|
|
84
|
+
|
|
85
|
+
The same app runs on your laptop and is shaped, from the first commit, to fan out across the edge without a rewrite. Full architecture and status in [The road to hyperscale](#the-road-to-hyperscale).
|
|
86
|
+
|
|
87
|
+
## Everything, at a glance
|
|
88
|
+
|
|
89
|
+
This is the full surface area. Every row works the moment `create` finishes, no plugins to install, no config to write.
|
|
90
|
+
|
|
91
|
+
| | |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| **Zero config** | One command scaffolds a working app. You never write an `index.html`, a `main.tsx`, a router, or a Vite / build config. The framework generates and owns all of it. |
|
|
94
|
+
| **Routing** | File-based. Dynamic, catch-all, optional catch-all, route groups, nested layouts, templates, loading and error boundaries, parallel slots, and intercepting routes. Every `href` and `params` is typed against your real files. |
|
|
95
|
+
| **Navigation** | `Link` / `NavLink`, programmatic `navigate` / `back` / `forward` / `refresh`, hover and viewport prefetch, scroll restoration, instant back/forward, and animated view transitions. |
|
|
96
|
+
| **Data** | A `loader` resolves before render. `useAction` / `<Form>` write then revalidate. An LRU loader cache with per-route `revalidate`. No fetch waterfalls, no `useEffect` data fetching. |
|
|
97
|
+
| **Rendering + SEO** | Per-route `<head>` baked into static HTML at build, plus `sitemap.xml`, `robots.txt`, `llms.txt`, OpenGraph, Twitter, JSON-LD, canonical, theme-color, early hints. SSG via `generateStaticParams`. |
|
|
98
|
+
| **Search** | Built-in site search over a compiler-baked metadata index, ranked, with a `usePageSearch` hook. Plus `llms.txt` so AI crawlers can read your site. |
|
|
99
|
+
| **Assets** | Imported images compressed to webp and resized via Vite + sharp. Fonts preloaded. React split into its own long-lived chunk. The build logs what it saved. |
|
|
100
|
+
| **Components** | Drop-in `Image` (no layout shift, lazy, blur), `Script` (load strategies, dedupe), `Form`, `Slot`, `Head`, all on a typed `Toil` global, zero imports. |
|
|
101
|
+
| **Realtime** | Typed channels: `connectChannel` / `useChannel`, reconnect built in, text or binary frames. WebSocket today, with first-class WebTransport over HTTP/3 coming (automatic WebSocket fallback). |
|
|
102
|
+
| **Server** | A typed ToilScript server compiled to a portable, native-speed module. `Request` / `Response` REST handlers, binary IO on both sides, and a typed RPC surface generated from your server. |
|
|
103
|
+
| **Agentic DX** | A dev toolbar with a live AI tab (hand off page context to Claude or ChatGPT), a Cmd+K palette, and scaffolded agent files (CLAUDE.md, AGENTS.md, Cursor, Copilot). |
|
|
104
|
+
| **Toolkit** | Strict TypeScript, ESLint, and Prettier shipped as presets, plus optional git init. Tailwind v4, Sass, Less, and Stylus a flag away. |
|
|
105
|
+
| **CLI** | `create`, `dev`, `build`, `start`, `configure`, `doctor` (with `--json` for CI), and `update`. |
|
|
106
|
+
|
|
107
|
+
## Routing
|
|
108
|
+
|
|
109
|
+
The filesystem is the router. Every convention below is implemented.
|
|
110
|
+
|
|
111
|
+
| File or folder | Route |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `index.tsx` | `/` |
|
|
114
|
+
| `about.tsx` | `/about` |
|
|
115
|
+
| `blog/[id].tsx` | `/blog/:id` |
|
|
116
|
+
| `docs/[...slug].tsx` | catch-all |
|
|
117
|
+
| `docs/[[...slug]].tsx` | optional catch-all |
|
|
118
|
+
| `(marketing)/about.tsx` | route group, adds no URL segment |
|
|
119
|
+
| `layout.tsx` | wraps the segment, persists across navigation |
|
|
120
|
+
| `template.tsx` | a layout that re-mounts on every navigation |
|
|
121
|
+
| `loading.tsx` | Suspense fallback while the route and its data load |
|
|
122
|
+
| `error.tsx` | error boundary for the segment |
|
|
123
|
+
| `global-error.tsx` | catches errors in the root layout itself |
|
|
124
|
+
| `404.tsx` | not-found page |
|
|
125
|
+
| `@modal/...` | parallel slot, placed with `<Toil.Slot name="modal" />` |
|
|
126
|
+
| `@modal/(.)photo/[id]` | intercepting route: modal on soft nav, full page on reload |
|
|
127
|
+
|
|
128
|
+
Navigation comes with it:
|
|
129
|
+
|
|
130
|
+
- **`<Toil.Link>`** and **`<Toil.NavLink>`** (active class + `aria-current`), with `href` checked against your real routes.
|
|
131
|
+
- **`navigate` / `back` / `forward` / `refresh`**, plus **`useRouter`**, **`useNavigate`**, **`useLocation`**, **`usePathname`**, **`useParams`**, **`useSearchParams`**, **`useNavigationPending`**.
|
|
132
|
+
- **Hover and viewport prefetching**, so chunks (and data) are warm before you click. Respects `saveData` and `data-no-prefetch`.
|
|
133
|
+
- **Scroll restoration** on back/forward, scroll-to-`#hash`, and scroll-to-top on new routes.
|
|
134
|
+
- **Instant navigation**: visited pages render synchronously, no flash.
|
|
135
|
+
- **View transitions** (`client.viewTransitions: true`) for animated page changes, respecting `prefers-reduced-motion`.
|
|
136
|
+
|
|
137
|
+
## Data and caching
|
|
138
|
+
|
|
139
|
+
Read with a `loader`, write with an action. Both keep the UI in sync without manual refetching, and the client caches loader results so repeat navigations are instant.
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
export const loader = async ({ params }: Toil.LoaderArgs) => fetchPost(params.id);
|
|
143
|
+
export const revalidate: Toil.Revalidate = 10; // reuse for 10s, false = forever, omit = every nav
|
|
144
|
+
|
|
145
|
+
function SaveButton({ title }: { title: string }) {
|
|
146
|
+
const save = Toil.useAction((t: string) => api.save(t), { revalidate: true });
|
|
147
|
+
return (
|
|
148
|
+
<button disabled={save.pending} onClick={() => void save.run(title)}>
|
|
149
|
+
{save.pending ? 'Saving' : 'Save'}
|
|
150
|
+
</button>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- **`loader`** resolves in parallel with the route chunk; the page suspends until ready (its `loading.tsx` shows).
|
|
156
|
+
- **`useLoaderData(loader)`** is typed straight from the loader, no generics.
|
|
157
|
+
- **Client cache**: an LRU of loader results keyed by path + search, with `revalidate` set per route (seconds, `false` for forever, or per-navigation). Prefetched entries are reused on commit.
|
|
158
|
+
- **`useAction`** and **`<Toil.Form>`** track pending and error state and revalidate the routes you name on success. `router.revalidate()` / `revalidate(href)` bust the cache after a mutation.
|
|
159
|
+
|
|
160
|
+
## Rendering and SEO
|
|
161
|
+
|
|
162
|
+
A single-page app serves an empty shell. ToilJS pre-renders each route's `<head>` at build, so Google, Facebook, Discord, Slack, and the AI crawlers see real per-page tags without running your JavaScript.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// toil.config.ts
|
|
166
|
+
export default defineConfig({
|
|
167
|
+
client: {
|
|
168
|
+
seo: {
|
|
169
|
+
url: 'https://example.com',
|
|
170
|
+
title: 'My App',
|
|
171
|
+
openGraph: { siteName: 'My App', type: 'website', image: '/og.png' },
|
|
172
|
+
twitter: { card: 'summary_large_image' },
|
|
173
|
+
jsonLd: { '@context': 'https://schema.org', '@type': 'WebSite' },
|
|
174
|
+
themeColor: '#2563ff', // also the Discord / Slack embed accent
|
|
175
|
+
preconnect: ['https://cdn.example.com'],
|
|
176
|
+
robots: { ai: 'allow' },
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- **Per-route `metadata`** (or `generateMetadata` derived from the loader's data) wins per page over layout defaults.
|
|
183
|
+
- **Static prerender** writes a `<route>/index.html` for every static route with that route's head baked in. **SSG** enumerates dynamic routes via `generateStaticParams` and bakes per-URL HTML.
|
|
184
|
+
- **`robots.txt`**, **`sitemap.xml`**, and **`llms.txt`** generated together.
|
|
185
|
+
- Full **OpenGraph**, **Twitter card**, **JSON-LD**, **canonical**, **theme-color**, and **`preconnect` / `dns-prefetch`** early hints. Output is XSS-hardened.
|
|
186
|
+
|
|
187
|
+
### AI search, on by default
|
|
188
|
+
|
|
189
|
+
Turn on SEO and the build emits an `llms.txt` describing your site for language models, plus a `robots.txt` with explicit per-bot rules. Allow or block GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, anthropic-ai, Google-Extended, PerplexityBot, CCBot, Applebot-Extended, Bytespider, Amazonbot, and Meta-ExternalAgent with one switch:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
seo: { llms: { instructions: 'Docs live at /docs.' }, robots: { ai: 'disallow' } }
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Your users get search too. The compiler bakes a static index of every page's title, description, and keywords, and `Toil.usePageSearch` (or the pure `searchPages`) returns ranked, navigable results.
|
|
196
|
+
|
|
197
|
+
## Assets and the Vite build
|
|
198
|
+
|
|
199
|
+
ToilJS owns Vite, for the dev server and for the ahead-of-time production build, and does the boring optimization for you. The build tells you what it did:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
$ npm run build
|
|
203
|
+
✓ optimized 3 images
|
|
204
|
+
client/hero.png
|
|
205
|
+
→ images/hero.webp 148.0 kB → 19.3 kB -87%
|
|
206
|
+
✓ preloaded 2 fonts
|
|
207
|
+
→ fonts/inter-latin.woff2 24.10 kB
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
- **Images** (Vite imagetools + sharp): every imported raster is compressed to webp, with resize and reformat via `?w=400;800&format=webp&as=srcset`. The build logs the savings.
|
|
211
|
+
- **Fonts**: bundled `@font-face` fonts get a `<link rel="preload">` so text paints sooner, also logged.
|
|
212
|
+
- **Chunking**: React is split into its own long-lived chunk; assets land in tidy `images/`, `fonts/`, and `css/` folders.
|
|
213
|
+
- **Node polyfills** (`Buffer`, `global`, `process`) for libraries that expect them.
|
|
214
|
+
- **Styling**: plain CSS out of the box, with Sass, Less, Stylus, and Tailwind v4 a `toiljs configure` away.
|
|
215
|
+
|
|
216
|
+
You never write an `index.html`, a `main.tsx`, or a Vite config. The framework generates and owns them.
|
|
217
|
+
|
|
218
|
+
## Components
|
|
219
|
+
|
|
220
|
+
Zero-import, on the `Toil` global:
|
|
221
|
+
|
|
222
|
+
- **`Image`** drops in for `<img>`: reserves space (no layout shift), lazy-loads, async-decodes, `priority` for the LCP image, `fill` + `objectFit`, optional blur placeholder.
|
|
223
|
+
- **`Script`** loads external or inline scripts with a `strategy` (`afterInteractive` / `lazyOnload` / `beforeInteractive`), deduplicated so a script never runs twice.
|
|
224
|
+
- **`Form`** submits to an action without a reload, revalidates on success, exposes pending state, optionally resets fields.
|
|
225
|
+
- **`Slot`** renders a parallel `@slot` route, the basis for modal overlays.
|
|
226
|
+
- **`Head`** / **`useHead`** / **`useTitle`** set the title and `<meta>` / `<link>` tags imperatively and compose across the tree.
|
|
227
|
+
|
|
228
|
+
## Realtime
|
|
229
|
+
|
|
230
|
+
One typed channel API for live data in both directions.
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
const messages = Toil.useChannel<Message>('/chat');
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`connectChannel` / `useChannel` / `resolveChannelUrl` handle connection, reconnection, and message decoding, text or binary frames. Today the channel runs over WebSocket. Next it rides **WebTransport** over HTTP/3: multiplexed bidirectional streams and datagrams over QUIC with no head-of-line blocking. Toil is built to be the **first framework to ship first-class WebTransport**, with automatic WebSocket fallback, so the same `useChannel` quietly upgrades to the fastest transport the client and network support, with no code change.
|
|
237
|
+
|
|
238
|
+
## The server: ToilScript + WebAssembly
|
|
239
|
+
|
|
240
|
+
Your backend is written in **ToilScript**, a TypeScript-syntax language that compiles to WebAssembly. You write request handlers; the compiler produces a single portable `.wasm` module.
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
// server/HelloHandler.ts
|
|
244
|
+
export class HelloHandler extends ToilHandler {
|
|
245
|
+
handle(req: Request): Response {
|
|
246
|
+
if (req.path == '/api/hello') return Response.json('{"hello":"world"}');
|
|
247
|
+
return Response.notFound();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
- **REST handlers**: `Request` (method, path, headers, body) in, `Response` out, with `text` / `html` / `json` / `notFound` / `badRequest` / `internalError` helpers and the full set of HTTP methods.
|
|
253
|
+
- **Binary IO on both sides**: `DataWriter`, `DataReader`, `FastMap`, and `FastSet` are shared client and server globals (and `toiljs/io`), so you can move structured bytes instead of paying the JSON tax.
|
|
254
|
+
- **Typed RPC (preview)**: tag a server function and the compiler generates a typed `Server.*` surface on the client, end to end, no hand-written glue. The typed pipeline is in place today; the network transport is landing next.
|
|
255
|
+
|
|
256
|
+
`toiljs start` self-hosts the built client and a WebSocket channel on [hyper-express](https://github.com/kartikk221/hyper-express) (backed by uWebSockets.js) for local and small deployments. For where this is headed at scale, see [The road to hyperscale](#the-road-to-hyperscale).
|
|
257
|
+
|
|
258
|
+
## Agentic tooling
|
|
259
|
+
|
|
260
|
+
`toiljs dev` injects a floating toolbar (stripped from production builds entirely, no flag, no leftover bytes) that surfaces the framework's live state: the matched route, params, and active slots; the loader cache with revalidate and clear buttons; the live `<head>` with an OpenGraph preview and an SEO checklist; resolved config flags and versions; a captured error log; and toggles for view and loader transitions. Press **Cmd/Ctrl+K** for a command palette to jump to any route or run a dev action.
|
|
261
|
+
|
|
262
|
+
It also ships an **AI tab**: hand off the current page's context (and its source) to Claude or ChatGPT in one click, or wire a provider for inline answers. The API key is read server-side only and never reaches the browser.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import { defineConfig, AiProvider } from 'toiljs/compiler';
|
|
266
|
+
|
|
267
|
+
export default defineConfig({
|
|
268
|
+
client: {
|
|
269
|
+
devtools: {
|
|
270
|
+
ai: {
|
|
271
|
+
provider: AiProvider.Anthropic, // or AiProvider.OpenAI, or a custom endpoint
|
|
272
|
+
model: 'claude-sonnet-4-6',
|
|
273
|
+
apiKeyEnv: 'ANTHROPIC_API_KEY', // read by the dev server only
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
And the `toiljs create` wizard scaffolds assistant files (CLAUDE.md, AGENTS.md, Cursor, and Copilot configs) so your repo is ready for coding agents on day one.
|
|
281
|
+
|
|
282
|
+
## The toolkit is the standard
|
|
283
|
+
|
|
284
|
+
ToilJS sets the toolchain so nobody argues about it. Strict TypeScript, ESLint (typescript-eslint, react-hooks, react-refresh, @eslint-react), and Prettier come configured and enforced from the first commit, shipped as `toiljs/tsconfig`, `toiljs/eslint`, and `toiljs/prettier`. New apps extend them automatically and can init git in the same step. Opt in to as much as you want, nothing to copy, nothing to bikeshed.
|
|
285
|
+
|
|
286
|
+
## Configuration
|
|
287
|
+
|
|
288
|
+
One file, `toil.config.ts`, typed with `defineConfig`. Every option has a sensible default, so most apps only set `seo`.
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
import { defineConfig } from 'toiljs/compiler';
|
|
292
|
+
|
|
293
|
+
export default defineConfig({
|
|
294
|
+
client: {
|
|
295
|
+
srcDir: 'client', // source root (default: client)
|
|
296
|
+
routesDir: 'routes', // route folder (default: routes)
|
|
297
|
+
base: '/', // base path (default: /)
|
|
298
|
+
port: 3000, // dev / start port (default: 3000)
|
|
299
|
+
images: true, // webp + resize pipeline (default: true)
|
|
300
|
+
fonts: true, // preload bundled fonts (default: true)
|
|
301
|
+
viewTransitions: false, // animated navigation (default: false)
|
|
302
|
+
transitions: false, // keep page during load (default: false)
|
|
303
|
+
devtools: true, // dev toolbar, or { ai } (default: true)
|
|
304
|
+
seo: {
|
|
305
|
+
// url, title, openGraph, twitter, jsonLd, robots, themeColor, ...
|
|
306
|
+
},
|
|
307
|
+
vite: {
|
|
308
|
+
// escape hatch: a full Vite InlineConfig, merged on top
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Set any feature to `false` to turn it off. `client.vite` is merged into the generated Vite config for the rare case you need to reach the bundler directly.
|
|
315
|
+
|
|
316
|
+
## CLI
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
toiljs create [name] scaffold a new app
|
|
320
|
+
toiljs dev dev server with HMR
|
|
321
|
+
toiljs build ahead-of-time production build
|
|
322
|
+
toiljs start self-host the built client + realtime channel
|
|
323
|
+
toiljs configure toggle styling and asset features on an existing app
|
|
324
|
+
toiljs doctor diagnose project setup and dependencies
|
|
325
|
+
toiljs update check for and apply dependency updates
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
- **`create [name]`** runs an interactive wizard: template (`app` or `minimal`), CSS flavor (`css` / `sass` / `less` / `stylus`), Tailwind, which AI assistant files to scaffold, image optimization, git init, and package manager (`npm` / `pnpm` / `yarn` / `bun`). Every prompt has a flag (`--template`, `--style`, `--tailwind`, `--ai`, `--images`, `--git`, `--install`, `--pm`), and `--yes` runs it non-interactively.
|
|
329
|
+
- **`dev`** starts the Vite dev server with HMR and regenerates the route table as you add or remove files. `--port` to override.
|
|
330
|
+
- **`build`** produces the optimized static client: prerendered HTML, `sitemap.xml`, `robots.txt`, `llms.txt`, and compressed images and fonts.
|
|
331
|
+
- **`start`** self-hosts the build and a realtime channel at `/_toil` on hyper-express. `--port` (default 3000), `--host` (pass `0.0.0.0` to expose on the network).
|
|
332
|
+
- **`configure`** edits an existing app: switch CSS preprocessor, toggle Tailwind or image optimization, and sync dependencies.
|
|
333
|
+
- **`doctor`** runs read-only checks across environment, routing, config, assets, and the server build, with a fix hint on each. `--json` for CI; it exits non-zero when a check fails.
|
|
334
|
+
- **`update`** checks the registry and groups available updates by major / minor / patch; pick what to apply or pass `-y` for all (`--target` sets the strategy).
|
|
335
|
+
|
|
336
|
+
## One file does a lot
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
339
|
+
// client/routes/posts/[id].tsx -> /posts/:id
|
|
340
|
+
interface Post {
|
|
341
|
+
title: string;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export const metadata: Toil.Metadata = { title: 'Post' }; // SEO, baked into the HTML at build
|
|
345
|
+
|
|
346
|
+
export const loader = async ({ params }: Toil.LoaderArgs): Promise<Post> => {
|
|
347
|
+
const res = await fetch(`/api/posts/${params.id}`); // runs before render, no useEffect
|
|
348
|
+
return res.json();
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
export default function PostPage() {
|
|
352
|
+
const post = Toil.useLoaderData(loader); // typed Post, no generics
|
|
353
|
+
return (
|
|
354
|
+
<article>
|
|
355
|
+
<h1>{post.title}</h1>
|
|
356
|
+
<Toil.Link href="/posts">All posts</Toil.Link> {/* href is type-checked */}
|
|
357
|
+
</article>
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
No imports. `Toil` is a fully-typed global, tree-shaken at build. The page renders with its data already loaded.
|
|
363
|
+
|
|
364
|
+
## Architecture
|
|
365
|
+
|
|
366
|
+
One pipeline, from your editor to planetary scale. The build pipeline and the React client ship today; the edge runtime, the ToilDB data layer, and Dacely Cloud are the roadmap (marked in purple).
|
|
367
|
+
|
|
368
|
+
```mermaid
|
|
369
|
+
flowchart TB
|
|
370
|
+
classDef today fill:#0e1520,stroke:#2563ff,stroke-width:2px,color:#cfe0ff;
|
|
371
|
+
classDef soon fill:#160f1f,stroke:#7c3aed,stroke-width:2px,color:#ead7ff,stroke-dasharray:6 4;
|
|
372
|
+
|
|
373
|
+
subgraph BUILD["BUILD, toiljs CLI, shipping today"]
|
|
374
|
+
direction TB
|
|
375
|
+
TSX["client/ React + TSX routes"] --> VITE["Vite<br/>HMR + ahead-of-time build"] --> ART["static client<br/>prerendered HTML<br/>sitemap, robots, llms<br/>optimized images + fonts"]
|
|
376
|
+
TS["server/ ToilScript .ts"] --> TSC["toilscript compiler"] --> WASM["one .wasm module"]
|
|
377
|
+
TOOL["toolkit: TypeScript, ESLint, Prettier, git<br/>dev toolbar: routes, loader cache, head/OG, errors<br/>AI tab to Claude / ChatGPT, Cmd-K palette<br/>typed RPC surface Server.*"]
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
CLIENTS["CLIENTS<br/>browsers, mobile, API clients, AI crawlers / LLMs"]
|
|
381
|
+
|
|
382
|
+
subgraph EDGE["EDGE, anycast, multi-region POPs, scale-out, roadmap"]
|
|
383
|
+
direction LR
|
|
384
|
+
SC["STATIC CLIENT<br/>React SPA + baked HTML<br/>images, fonts, css<br/>served from CDN / edge"]
|
|
385
|
+
RT["WASM EDGE RUNTIME<br/>your ToilScript server as one .wasm<br/>isolated per-core tenant at line rate<br/>Request to handler to Response<br/>realtime channels, binary IO<br/>x many tenants x many POPs"]
|
|
386
|
+
SC <-->|"typed RPC Server.*"| RT
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
subgraph DATA["ToilDB, edge-replicated typed data, roadmap"]
|
|
390
|
+
direction LR
|
|
391
|
+
MODES["collections<br/>owned, eventLog, counter, set<br/>unique, escrow, snapshot<br/>local reads fast, CRDT writes merge everywhere<br/>owned writes fast at owner, global claims slow"]
|
|
392
|
+
DUR["durable store<br/>structured records"]
|
|
393
|
+
BLOB["blob store<br/>large objects"]
|
|
394
|
+
MODES --> DUR
|
|
395
|
+
MODES --> BLOB
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
CTRL["DACELY CLOUD, control plane, roadmap<br/>deploy, distribute, scale<br/>client to the edge, .wasm to the runtime, data replicated"]
|
|
399
|
+
|
|
400
|
+
ART -->|deploys| SC
|
|
401
|
+
WASM -->|deploys| RT
|
|
402
|
+
CLIENTS -->|"HTTP/1.1 + WebSocket today<br/>HTTP/3, QUIC, WebTransport roadmap<br/>TLS today, post-quantum roadmap"| EDGE
|
|
403
|
+
RT -->|"region-replicated"| DATA
|
|
404
|
+
CTRL -. orchestrates .-> EDGE
|
|
405
|
+
CTRL -. orchestrates .-> DATA
|
|
406
|
+
|
|
407
|
+
class TSX,VITE,ART,TS,TSC,WASM,TOOL,CLIENTS today;
|
|
408
|
+
class SC,RT,MODES,DUR,BLOB,CTRL soon;
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
<details>
|
|
412
|
+
<summary>Same diagram as plain ASCII (for npm and text-only views)</summary>
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
┌──────────────────────────────────────────────────────────────────────────┐
|
|
416
|
+
│ BUILD toiljs CLI [today] │
|
|
417
|
+
│ │
|
|
418
|
+
│ client/ React + TSX routes ──▶ Vite (HMR ahead-of-time build) ──┐ │
|
|
419
|
+
│ server/ ToilScript (.ts) ──▶ toilscript compiler ──▶ one .wasm │ │
|
|
420
|
+
│ │ │
|
|
421
|
+
│ toolkit TypeScript ESLint Prettier git (opt-in presets) │ │
|
|
422
|
+
│ dev toolbar: routes loader cache head/OG errors │ │
|
|
423
|
+
│ AI tab → Claude / ChatGPT ⌘K palette │ │
|
|
424
|
+
│ emits static client prerendered HTML sitemap robots llms │ │
|
|
425
|
+
│ optimized images / fonts typed RPC surface (Server.*) │ │
|
|
426
|
+
└───────────────────────────────────────────────────────────────┬─────┬───┘
|
|
427
|
+
deploys ▼ │ │ ▼
|
|
428
|
+
┌──────────────────────────────────────────────────────────────────────────┐
|
|
429
|
+
│ CLIENTS │
|
|
430
|
+
│ browsers mobile webviews API clients AI crawlers/LLMs │
|
|
431
|
+
└───────────────────────────────────┬──────────────────────────────────────┘
|
|
432
|
+
HTTP/1.1 + WebSocket [today] │ HTTP/3 QUIC WebTransport [soon]
|
|
433
|
+
TLS [today] │ post-quantum transport [soon]
|
|
434
|
+
▼
|
|
435
|
+
╔══════════════════════════════════════════════════════════════════════════╗
|
|
436
|
+
║ EDGE anycast multi-region POPs scale-out [soon] ║
|
|
437
|
+
║ ║
|
|
438
|
+
║ ┌─────────────────────────┐ ┌─────────────────────────────────┐ ║
|
|
439
|
+
║ │ STATIC CLIENT │ │ WASM EDGE RUNTIME │ ║
|
|
440
|
+
║ │ React SPA + baked HTML │ │ your ToilScript server as one │ ║
|
|
441
|
+
║ │ images fonts css │ typed│ .wasm, run as an isolated │ ║
|
|
442
|
+
║ │ served from CDN / edge │◀──RPC─▶│ per-core tenant at line rate │ ║
|
|
443
|
+
║ │ │ Server.* Request ▶ handler ▶ Response │ ║
|
|
444
|
+
║ │ llms robots sitemap │ │ realtime channels binary IO │ ║
|
|
445
|
+
║ └─────────────────────────┘ └───────────────┬─────────────────┘ ║
|
|
446
|
+
║ instant, cacheable × many tenants × many POPs ║
|
|
447
|
+
╚═══════════════════════════════════════════════════════╪══════════════════╝
|
|
448
|
+
▼ region-replicated
|
|
449
|
+
╔══════════════════════════════════════════════════════════════════════════╗
|
|
450
|
+
║ ToilDB edge-replicated, typed data layer [soon] ║
|
|
451
|
+
║ ║
|
|
452
|
+
║ collections: owned eventLog counter set unique escrow ║
|
|
453
|
+
║ snapshot (the method name tells you the cost) ║
|
|
454
|
+
║ local reads fast CRDT writes merge everywhere ║
|
|
455
|
+
║ owned writes fast at the owner global claims explicitly slow ║
|
|
456
|
+
║ ║
|
|
457
|
+
║ ┌──────────────────────┐ ┌──────────────────────┐ ║
|
|
458
|
+
║ │ durable store │ │ blob store │ ║
|
|
459
|
+
║ │ structured records │ │ large objects │ ║
|
|
460
|
+
║ └──────────────────────┘ └──────────────────────┘ ║
|
|
461
|
+
╚═══════════════════════════════════════════════════════╪══════════════════╝
|
|
462
|
+
▼
|
|
463
|
+
╔══════════════════════════════════════════════════════════════════════════╗
|
|
464
|
+
║ DACELY CLOUD control plane: deploy distribute scale [soon] ║
|
|
465
|
+
║ push your app ─▶ client to the edge, .wasm to the runtime, data replicated ║
|
|
466
|
+
╚══════════════════════════════════════════════════════════════════════════╝
|
|
467
|
+
|
|
468
|
+
[today] shipping now [soon] architecture + roadmap, not yet GA
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
</details>
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## The road to hyperscale
|
|
476
|
+
|
|
477
|
+
> **Architecture and roadmap.** This section is where Toil is going, not what ships in the box today. The framework above is real and usable now; the platform below is the design it is being built toward.
|
|
478
|
+
|
|
479
|
+
The reason the client is static and the server is WebAssembly is that the WebAssembly runs on a runtime engineered from scratch for the edge. Toil's backend treats your compiled server as an isolated tenant and is built to serve it at line rate, so the same app that runs on your laptop is designed to scale out across the edge without a rewrite.
|
|
480
|
+
|
|
481
|
+
<div align="center">
|
|
482
|
+
|
|
483
|
+

|
|
484
|
+

|
|
485
|
+

|
|
486
|
+

|
|
487
|
+
|
|
488
|
+
</div>
|
|
489
|
+
|
|
490
|
+
- **A purpose-built WebAssembly edge runtime.** Your server runs as an isolated WebAssembly tenant on a runtime engineered for line-rate, multi-gigabit throughput and per-tenant isolation, not on a general-purpose Node process.
|
|
491
|
+
- **HTTP/3 and WebTransport.** Bidirectional streams and datagrams over QUIC for interactive, multiplexed realtime, beyond the WebSocket channel that ships today.
|
|
492
|
+
- **ToilDB, an edge-replicated data layer.** Typed collections declared in ToilScript, where the method name tells you the cost: local reads are fast, appends and CRDT counters/sets merge everywhere, owned writes are fast at the owner, and rare global claims are explicitly slow. Hyperscale data, without a per-query consistency knob to get wrong.
|
|
493
|
+
- **Post-quantum-ready transport.** Forward-looking encryption for the edge as the QUIC layer lands.
|
|
494
|
+
- **Dacely Cloud.** Managed hosting for the whole stack: push your app, the static client goes to the edge and your WebAssembly server runs on the runtime above.
|
|
495
|
+
|
|
496
|
+
This is the spine the framework was shaped around. Today you write a typed, file-based React app with a WebAssembly server; the roadmap is the platform that runs it at planetary scale.
|
|
497
|
+
|
|
498
|
+
## Tech
|
|
499
|
+
|
|
500
|
+
<div align="center">
|
|
501
|
+
|
|
502
|
+
<img src="https://img.shields.io/badge/React_19-20232a?style=for-the-badge&logo=react&logoColor=61dafb" alt="React 19" />
|
|
503
|
+
<img src="https://img.shields.io/badge/TypeScript-3178c6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
504
|
+
<img src="https://img.shields.io/badge/Vite-646cff?style=for-the-badge&logo=vite&logoColor=white" alt="Vite" />
|
|
505
|
+
<img src="https://img.shields.io/badge/WebAssembly-654ff0?style=for-the-badge&logo=webassembly&logoColor=white" alt="WebAssembly" />
|
|
506
|
+
<img src="https://img.shields.io/badge/ToilScript-cb9820?style=for-the-badge&logoColor=white" alt="ToilScript" />
|
|
507
|
+
<img src="https://img.shields.io/badge/sharp-99cc00?style=for-the-badge&logo=sharp&logoColor=white" alt="sharp" />
|
|
508
|
+
<img src="https://img.shields.io/badge/ESLint-4b32c3?style=for-the-badge&logo=eslint&logoColor=white" alt="ESLint" />
|
|
509
|
+
<img src="https://img.shields.io/badge/Prettier-f7b93e?style=for-the-badge&logo=prettier&logoColor=black" alt="Prettier" />
|
|
510
|
+
<img src="https://img.shields.io/badge/Tailwind_v4-06b6d4?style=for-the-badge&logo=tailwindcss&logoColor=white" alt="Tailwind v4" />
|
|
511
|
+
|
|
512
|
+
</div>
|
|
513
|
+
|
|
514
|
+
React 19, TypeScript, Vite, [ToilScript](https://www.npmjs.com/package/toilscript) (TypeScript syntax, compiles to WebAssembly), Vite imagetools + sharp, ESLint (typescript-eslint, react-hooks, react-refresh, @eslint-react), Prettier, Tailwind v4 (optional).
|
|
515
|
+
|
|
516
|
+
## Start
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
npx toiljs create my-app
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Everything in the framework half of this README is already on. You just build the app.
|
|
523
|
+
|
|
524
|
+
<div align="center"><br/><sub>Apache-2.0, <a href="https://toil.org">toil.org</a></sub></div>
|