toiljs 0.0.16 → 0.0.20
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/CHANGELOG.md +128 -0
- package/README.md +313 -128
- package/as-pect.config.js +1 -1
- 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 -697
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/dev/devtools.js +42 -5
- 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/rpc.d.ts +1 -0
- package/build/client/rpc.js +37 -0
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/config.js +3 -1
- package/build/compiler/docs.js +69 -7
- package/build/compiler/generate.js +5 -4
- package/build/compiler/index.d.ts +1 -0
- package/build/compiler/index.js +30 -1
- package/build/compiler/plugin.js +80 -8
- package/build/compiler/seo.js +15 -1
- package/build/compiler/ssg.js +7 -1
- 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/eslint.config.js +1 -1
- package/examples/basic/client/routes/features/index.tsx +1 -1
- package/examples/basic/client/routes/io.tsx +6 -7
- package/examples/basic/client/routes/rest.tsx +84 -0
- package/examples/basic/client/routes/rpc.tsx +43 -0
- package/package.json +19 -7
- package/presets/prettier-plugin.js +51 -0
- package/presets/prettier.json +1 -0
- 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 +45 -3
- package/src/cli/create.ts +16 -6
- package/src/cli/diagnostics.ts +81 -0
- package/src/cli/doctor.ts +384 -7
- package/src/cli/index.ts +11 -2
- package/src/client/dev/devtools.tsx +49 -4
- package/src/client/errors.ts +11 -0
- package/src/client/index.ts +2 -0
- package/src/client/rpc.ts +64 -0
- package/src/compiler/config.ts +3 -1
- package/src/compiler/docs.ts +69 -7
- package/src/compiler/generate.ts +6 -5
- package/src/compiler/index.ts +50 -1
- package/src/compiler/plugin.ts +99 -11
- package/src/compiler/seo.ts +23 -3
- package/src/compiler/ssg.ts +10 -1
- package/src/compiler/vite.ts +34 -0
- package/src/io/FastMap.ts +24 -0
- package/src/io/FastSet.ts +15 -1
- package/src/io/codec.ts +217 -0
- package/src/io/index.ts +1 -2
- package/src/io/types.ts +2 -1
- package/test/assembly/example.spec.ts +14 -4
- package/test/doctor.test.ts +65 -0
- package/test/errors.test.ts +21 -0
- package/test/io.test.ts +65 -41
- package/test/prettier-plugin.test.ts +46 -0
- package/test/rpc.test.ts +50 -0
- 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/tsconfig.json +1 -1
- package/tsconfig.server.json +1 -1
- 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/toilconfig.json +0 -30
package/README.md
CHANGED
|
@@ -4,16 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
# ToilJS
|
|
6
6
|
|
|
7
|
-
###
|
|
7
|
+
### The fullstack React framework, built for hyperscale.
|
|
8
8
|
|
|
9
|
-
|
|
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.
|
|
10
16
|
|
|
11
17
|
<br/>
|
|
12
18
|
|
|
13
19
|
[](https://www.npmjs.com/package/toiljs)
|
|
14
20
|
[](https://www.typescriptlang.org/)
|
|
15
21
|
[](https://react.dev/)
|
|
16
|
-
[](#
|
|
22
|
+
[](#the-server-toilscript--webassembly)
|
|
23
|
+
[](#realtime)
|
|
17
24
|
[](./LICENSE)
|
|
18
25
|
|
|
19
26
|
<br/>
|
|
@@ -22,12 +29,15 @@
|
|
|
22
29
|
<img src="https://img.shields.io/badge/TypeScript-3178c6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
23
30
|
<img src="https://img.shields.io/badge/Vite-646cff?style=for-the-badge&logo=vite&logoColor=white" alt="Vite" />
|
|
24
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" />
|
|
25
33
|
|
|
26
34
|
</div>
|
|
27
35
|
|
|
28
36
|
---
|
|
29
37
|
|
|
30
|
-
React
|
|
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.
|
|
31
41
|
|
|
32
42
|
```bash
|
|
33
43
|
npx toiljs create my-app
|
|
@@ -35,93 +45,68 @@ cd my-app
|
|
|
35
45
|
npm run dev
|
|
36
46
|
```
|
|
37
47
|
|
|
38
|
-
Drop a `.tsx` file in `client/routes/` and it is a route: typed, code-split, prefetched, data loaded before render.
|
|
39
|
-
|
|
40
|
-
## Built for scale
|
|
41
|
-
|
|
42
|
-
The backend is the point. `server/` is [ToilScript](https://www.npmjs.com/package/toilscript) compiled to a single WebAssembly module (Binaryen), and `toiljs start` self-hosts the app on [hyper-express](https://github.com/kartikk221/hyper-express), backed by [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js), the same core that serves millions of HTTP requests per second.
|
|
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.
|
|
43
49
|
|
|
44
50
|
<div align="center">
|
|
45
51
|
|
|
46
|
-

|
|
47
|
-

|
|
48
|
-

|
|
49
|
-

|
|
50
|
-
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
- **WebAssembly compute.** Your server logic runs as native-speed WASM, not interpreted JS.
|
|
54
|
-
- **Binary on the wire.** The client and server share `BinaryWriter` / `BinaryReader` and `FastMap` / `FastSet`, so you move bytes, not JSON.
|
|
55
|
-
- **HTTP/3 and WebTransport** over QUIC, low-latency streaming without the TCP head-of-line tax.
|
|
56
|
-
- **Built for 50 Gbit/s on commodity hardware** and millions of requests per second, not toy demos.
|
|
57
|
-
|
|
58
|
-
```ts
|
|
59
|
-
// server/index.ts
|
|
60
|
-
export function add(a: i32, b: i32): i32 {
|
|
61
|
-
return a + b;
|
|
62
|
-
}
|
|
63
52
|
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- **Typed routes**: `href` and `params` checked against your real files
|
|
74
|
-
- **Loaders and mutations** with caching and revalidation, no data library, no `useEffect` fetching
|
|
75
|
-
- **Parallel and intercepting routes** for modals and dashboards
|
|
76
|
-
- **Instant navigation** and **animated view transitions**
|
|
77
|
-
- **WebAssembly backend** on uWebSockets, with **binary IO** on both sides
|
|
78
|
-
|
|
79
|
-
Anywhere else, that is a dozen packages and their config. Most teams wire three and ship the rest half-done.
|
|
80
|
-
|
|
81
|
-
## AI-ready
|
|
82
|
-
|
|
83
|
-
ToilJS treats AI crawlers as first-class. Turn on SEO and the build emits an `llms.txt` describing your site for LLMs, and a `robots.txt` with explicit rules for the AI bots, 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.
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
seo: { llms: { instructions: 'Docs live at /docs.' }, robots: { ai: 'disallow' } }
|
|
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)
|
|
87
62
|
```
|
|
88
63
|
|
|
89
|
-
|
|
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.
|
|
90
67
|
|
|
91
|
-
|
|
92
|
-
User-agent: *
|
|
93
|
-
Allow: /
|
|
68
|
+
## Built for scale
|
|
94
69
|
|
|
95
|
-
|
|
96
|
-
Disallow: /
|
|
70
|
+
Toil's architecture is the scaling story. There is no monolith to keep warm and nothing re-rendering your pages on every request.
|
|
97
71
|
|
|
98
|
-
|
|
99
|
-
|
|
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.
|
|
100
76
|
|
|
101
|
-
|
|
102
|
-
Disallow: /
|
|
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:
|
|
103
78
|
|
|
104
|
-
|
|
105
|
-
|
|
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.
|
|
106
84
|
|
|
107
|
-
The
|
|
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).
|
|
108
86
|
|
|
109
87
|
## Everything, at a glance
|
|
110
88
|
|
|
89
|
+
This is the full surface area. Every row works the moment `create` finishes, no plugins to install, no config to write.
|
|
90
|
+
|
|
111
91
|
| | |
|
|
112
92
|
| --- | --- |
|
|
113
|
-
| **
|
|
114
|
-
| **
|
|
115
|
-
| **
|
|
116
|
-
| **
|
|
117
|
-
| **
|
|
118
|
-
| **
|
|
119
|
-
| **
|
|
120
|
-
| **
|
|
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`. |
|
|
121
106
|
|
|
122
107
|
## Routing
|
|
123
108
|
|
|
124
|
-
The filesystem is the router.
|
|
109
|
+
The filesystem is the router. Every convention below is implemented.
|
|
125
110
|
|
|
126
111
|
| File or folder | Route |
|
|
127
112
|
| --- | --- |
|
|
@@ -144,14 +129,14 @@ Navigation comes with it:
|
|
|
144
129
|
|
|
145
130
|
- **`<Toil.Link>`** and **`<Toil.NavLink>`** (active class + `aria-current`), with `href` checked against your real routes.
|
|
146
131
|
- **`navigate` / `back` / `forward` / `refresh`**, plus **`useRouter`**, **`useNavigate`**, **`useLocation`**, **`usePathname`**, **`useParams`**, **`useSearchParams`**, **`useNavigationPending`**.
|
|
147
|
-
- **Hover and viewport prefetching**, so chunks are warm before you click.
|
|
132
|
+
- **Hover and viewport prefetching**, so chunks (and data) are warm before you click. Respects `saveData` and `data-no-prefetch`.
|
|
148
133
|
- **Scroll restoration** on back/forward, scroll-to-`#hash`, and scroll-to-top on new routes.
|
|
149
134
|
- **Instant navigation**: visited pages render synchronously, no flash.
|
|
150
135
|
- **View transitions** (`client.viewTransitions: true`) for animated page changes, respecting `prefers-reduced-motion`.
|
|
151
136
|
|
|
152
|
-
## Data
|
|
137
|
+
## Data and caching
|
|
153
138
|
|
|
154
|
-
Read with a `loader`, write with an action. Both keep the UI in sync without manual refetching.
|
|
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.
|
|
155
140
|
|
|
156
141
|
```tsx
|
|
157
142
|
export const loader = async ({ params }: Toil.LoaderArgs) => fetchPost(params.id);
|
|
@@ -169,20 +154,10 @@ function SaveButton({ title }: { title: string }) {
|
|
|
169
154
|
|
|
170
155
|
- **`loader`** resolves in parallel with the route chunk; the page suspends until ready (its `loading.tsx` shows).
|
|
171
156
|
- **`useLoaderData(loader)`** is typed straight from the loader, no generics.
|
|
172
|
-
-
|
|
173
|
-
- **`useAction`** and **`<Toil.Form>`** track pending and error state and revalidate on success.
|
|
174
|
-
|
|
175
|
-
## Components
|
|
176
|
-
|
|
177
|
-
Zero-import, on the `Toil` global:
|
|
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.
|
|
178
159
|
|
|
179
|
-
|
|
180
|
-
- **`Script`** loads external or inline scripts with a `strategy` (`afterInteractive` / `lazyOnload` / `beforeInteractive`), deduplicated so a script never runs twice.
|
|
181
|
-
- **`Form`** submits to an action without a reload, revalidates on success, exposes pending state, optionally resets fields.
|
|
182
|
-
- **`Slot`** renders a parallel `@slot` route, the basis for modal overlays.
|
|
183
|
-
- **`Head`** / **`useHead`** / **`useTitle`** set the title and `<meta>` / `<link>` tags imperatively and compose across the tree.
|
|
184
|
-
|
|
185
|
-
## Head and SEO
|
|
160
|
+
## Rendering and SEO
|
|
186
161
|
|
|
187
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.
|
|
188
163
|
|
|
@@ -205,14 +180,23 @@ export default defineConfig({
|
|
|
205
180
|
```
|
|
206
181
|
|
|
207
182
|
- **Per-route `metadata`** (or `generateMetadata` derived from the loader's data) wins per page over layout defaults.
|
|
208
|
-
- **Static prerender** writes a `<route>/index.html` for every static route with that route's head baked in.
|
|
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.
|
|
209
184
|
- **`robots.txt`**, **`sitemap.xml`**, and **`llms.txt`** generated together.
|
|
210
|
-
- Full **OpenGraph
|
|
211
|
-
- Output is **XSS-hardened**: attribute values and inline JSON-LD are escaped so injected data can't break out.
|
|
185
|
+
- Full **OpenGraph**, **Twitter card**, **JSON-LD**, **canonical**, **theme-color**, and **`preconnect` / `dns-prefetch`** early hints. Output is XSS-hardened.
|
|
212
186
|
|
|
213
|
-
|
|
187
|
+
### AI search, on by default
|
|
214
188
|
|
|
215
|
-
|
|
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:
|
|
216
200
|
|
|
217
201
|
```
|
|
218
202
|
$ npm run build
|
|
@@ -223,47 +207,59 @@ $ npm run build
|
|
|
223
207
|
→ fonts/inter-latin.woff2 24.10 kB
|
|
224
208
|
```
|
|
225
209
|
|
|
226
|
-
- **Images** (
|
|
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.
|
|
227
211
|
- **Fonts**: bundled `@font-face` fonts get a `<link rel="preload">` so text paints sooner, also logged.
|
|
228
212
|
- **Chunking**: React is split into its own long-lived chunk; assets land in tidy `images/`, `fonts/`, and `css/` folders.
|
|
229
213
|
- **Node polyfills** (`Buffer`, `global`, `process`) for libraries that expect them.
|
|
230
214
|
- **Styling**: plain CSS out of the box, with Sass, Less, Stylus, and Tailwind v4 a `toiljs configure` away.
|
|
231
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
|
+
|
|
232
228
|
## Realtime
|
|
233
229
|
|
|
234
|
-
|
|
230
|
+
One typed channel API for live data in both directions.
|
|
235
231
|
|
|
236
232
|
```tsx
|
|
237
233
|
const messages = Toil.useChannel<Message>('/chat');
|
|
238
234
|
```
|
|
239
235
|
|
|
240
|
-
`connectChannel` / `useChannel` / `resolveChannelUrl` handle connection, reconnection, and message decoding.
|
|
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.
|
|
241
237
|
|
|
242
|
-
##
|
|
238
|
+
## The server: ToilScript + WebAssembly
|
|
243
239
|
|
|
244
|
-
|
|
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.
|
|
245
241
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
+
```
|
|
249
251
|
|
|
250
|
-
|
|
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.
|
|
251
255
|
|
|
252
|
-
|
|
253
|
-
toiljs create [name] scaffold a new app (styling, AI files, package manager)
|
|
254
|
-
toiljs dev dev server with HMR
|
|
255
|
-
toiljs build production build
|
|
256
|
-
toiljs start self-host the build (hyper-express / uWebSockets)
|
|
257
|
-
toiljs configure toggle styling, image, font, and SEO features
|
|
258
|
-
toiljs doctor diagnose project setup and dependencies (--json for CI)
|
|
259
|
-
toiljs update check for and apply dependency updates (-y to apply all)
|
|
260
|
-
```
|
|
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).
|
|
261
257
|
|
|
262
|
-
##
|
|
258
|
+
## Agentic tooling
|
|
263
259
|
|
|
264
|
-
`toiljs dev` injects a floating toolbar (
|
|
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.
|
|
265
261
|
|
|
266
|
-
It also ships an **AI tab**: hand off the current page's context to Claude or ChatGPT in one click, or wire a provider for inline answers. The key is read server-side and never reaches the browser.
|
|
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.
|
|
267
263
|
|
|
268
264
|
```ts
|
|
269
265
|
import { defineConfig, AiProvider } from 'toiljs/compiler';
|
|
@@ -281,24 +277,61 @@ export default defineConfig({
|
|
|
281
277
|
});
|
|
282
278
|
```
|
|
283
279
|
|
|
284
|
-
|
|
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.
|
|
285
281
|
|
|
286
|
-
##
|
|
282
|
+
## The toolkit is the standard
|
|
287
283
|
|
|
288
|
-
|
|
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.
|
|
289
285
|
|
|
290
|
-
|
|
291
|
-
<img src="https://img.shields.io/badge/TypeScript-3178c6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
292
|
-
<img src="https://img.shields.io/badge/Vite-646cff?style=for-the-badge&logo=vite&logoColor=white" alt="Vite" />
|
|
293
|
-
<img src="https://img.shields.io/badge/WebAssembly-654ff0?style=for-the-badge&logo=webassembly&logoColor=white" alt="WebAssembly" />
|
|
294
|
-
<img src="https://img.shields.io/badge/sharp-99cc00?style=for-the-badge&logo=sharp&logoColor=white" alt="sharp" />
|
|
295
|
-
<img src="https://img.shields.io/badge/ESLint-4b32c3?style=for-the-badge&logo=eslint&logoColor=white" alt="ESLint" />
|
|
296
|
-
<img src="https://img.shields.io/badge/Prettier-f7b93e?style=for-the-badge&logo=prettier&logoColor=black" alt="Prettier" />
|
|
297
|
-
<img src="https://img.shields.io/badge/Tailwind_v4-06b6d4?style=for-the-badge&logo=tailwindcss&logoColor=white" alt="Tailwind v4" />
|
|
286
|
+
## Configuration
|
|
298
287
|
|
|
299
|
-
|
|
288
|
+
One file, `toil.config.ts`, typed with `defineConfig`. Every option has a sensible default, so most apps only set `seo`.
|
|
300
289
|
|
|
301
|
-
|
|
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).
|
|
302
335
|
|
|
303
336
|
## One file does a lot
|
|
304
337
|
|
|
@@ -328,12 +361,164 @@ export default function PostPage() {
|
|
|
328
361
|
|
|
329
362
|
No imports. `Toil` is a fully-typed global, tree-shaken at build. The page renders with its data already loaded.
|
|
330
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
|
+
|
|
331
516
|
## Start
|
|
332
517
|
|
|
333
518
|
```bash
|
|
334
519
|
npx toiljs create my-app
|
|
335
520
|
```
|
|
336
521
|
|
|
337
|
-
Everything in this README is already on. You just build the app.
|
|
522
|
+
Everything in the framework half of this README is already on. You just build the app.
|
|
338
523
|
|
|
339
|
-
<div align="center"><br/><sub>Apache-2.0</sub></div>
|
|
524
|
+
<div align="center"><br/><sub>Apache-2.0, <a href="https://toil.org">toil.org</a></sub></div>
|
package/as-pect.config.js
CHANGED