Checked before it runs
quillo check holds the program to its types, records, list and map shapes, effects and error types, and warns about SQL built from values.
The cells behind this page are Conway's Life: a Quillo component running in your browser. Move your pointer across them.
One HERO is not Awesome
? :, template strings and JSX-style HTML, without the surprises.Ready to use
.qwe file each, light and dark, keyboard and screen reader ready.DatePicker · CommandPalette · DataTable · KanbanBoard · CandlestickChartBrowse the components →628pluginsWhat the standard library leaves out, in Rust: one .qwer file each, with its version, its example, and a test that runs before every release.Excel files · PDF documents · JWT · QR codes · Email over SMTP · RedisBrowse the plugins →Tour
:id(int) matches only digits.| pipes a request through middleware, and reply answers from anywhere.route GET /hello/:name = `Hello, ${name}!`route POST /orders { json: { type: "order" | "refund", qty: int } } { reply 201 { accepted: true, qty }}route GET /feed ? { page: int = 1 } with db = request | auth.required | load_feed(page) | render_feedDemo
This page is a Quillo program. The component below was rendered on the server, and your browser took it over. Add an item, or click one to tick it off.
component Todo() { state items = [ { id: 1, text: "Read the tour", done: true }, { id: 2, text: "Write a route", done: false }, ] state draft = "" let left = items | filter((i) => !i.done) | len <form.todo onsubmit={() => { if trim(draft) != "" { items = items + [{ id: len(items) + 1, text: draft, done: false }] draft = "" } }}> <input value={draft} placeholder="Add something…"/> <ul>{for i in items => <li key={i.id} class={i.done && "done"} onclick={() => { items = items | map((j) => j.id == i.id ? merge(j, { done: !j.done }) : j) }}>{i.text}</li> }</ul> <small>{left} left</small> </form>}Speed
math, stats and vec give Python's exact answers, worked on by every core. How many times faster than Python 3.9, on a million floats (log scale; hover for timings):
stats.stdev1037×Quillo 0.65 ms · Python 674 msstats.mean611×Quillo 0.35 ms · Python 214 msstats.describe449×Quillo 1.7 ms · Python 764 ms (by hand)stats.histogram210×Quillo 0.6 ms · Python 126 ms (a loop)stats.correlation176×Quillo 1.4 ms · Python 246 msstats.linear_regression140×Quillo 1.3 ms · Python 182 msstats.median34×Quillo 1.3 ms · Python 44 mssort10×Quillo 4.6 ms · Python 46 msComponents compile to JavaScript with fine-grained signals: assigning state updates the places that show it, with no virtual DOM. In the keyed js-framework-benchmark app, driven in headless Chrome, each operation is timed from the click until the page is laid out. The total is the geometric mean of each time over the fastest one's, so 1.00 is the fastest and lower is better (hover for script time alone):
| Operation | Plain JS | Quillo | Solid | Svelte | Vue | Preact | React |
|---|---|---|---|---|---|---|---|
| Create 1,000 rows | 10.9 | 11.3 | 10.7 | 11.0 | 12.3 | 13.7 | 12.3 |
| Replace 1,000 rows | 11.2 | 12.0 | 11.7 | 12.2 | 13.6 | 15.7 | 15.6 |
| Update every 10th row | 2.30 | 2.70 | 2.40 | 2.40 | 3.60 | 2.90 | 2.80 |
| Select a row | 0.100 | 0.100 | 0.100 | 0.200 | 1.00 | 0.400 | 0.300 |
| Swap two rows | 0.800 | 0.900 | 0.900 | 1.00 | 1.80 | 11.3 | 12.0 |
| Remove a row | 0.800 | 0.900 | 0.900 | 0.900 | 1.90 | 1.10 | 1.00 |
| Create 10,000 rows | 118 | 129 | 123 | 125 | 133 | 157 | 220 |
| Append 1,000 rows | 12.2 | 13.1 | 12.3 | 12.3 | 15.1 | 15.7 | 14.5 |
| Clear 1,000 rows | 1.10 | 1.20 | 1.20 | 1.30 | 1.40 | 1.50 | 2.90 |
| Memory, 1,000 rows (MB) | 0.781 | 2.01 | 1.69 | 2.05 | 3.86 | 3.17 | 3.71 |
| Script, compressed (KB) | inline | 12.6 | 6.52 | 13.1 | 64.1 | 8.50 | 58.2 |
Medians of several runs, on an Apple M-series laptop (10 cores) in headless Chrome. Run it yourself with node ui/run.js; the apps are in quillolang/benchmarks.
Requests a second from one process, kept busy by 64 connections from the same machine: plain text, JSON, TechEmpower's Fortunes without a database (sorted, escaped HTML, computed on every request) and a 10,000-step arithmetic loop, which Quillo compiles to machine code.
Quillo: 1.16× the next, 1.67× the slowest
Quillo: 1.14× the next, 1.66× the slowest
Quillo: 1.07× the next, 2.02× the slowest
Quillo: 1.08× the next, 1.13× the slowest
Each server keeps about one core busy. Run it yourself with node server/run.cjs 8; the servers and the load generator are in quillolang/benchmarks.
And more
quillo check holds the program to its types, records, list and map shapes, effects and error types, and warns about SQL built from values.
Text is escaped, cross-site posts are refused, sessions are signed cookies and javascript: URLs are blocked.
Or PostgreSQL or MySQL, with the same functions, and several at once. Transactions nest, and migrations run in order, once: the guide.
Packets on a UDP port, messages to pages as WebTransport datagrams, a camera's RTP stream in any page, video calls from the pages' own cameras, answers streamed as they are made: the guide.
t("cart.items", { count }) picks plural forms by the language's rules, on the server and in components.
Split a part of an app into its own server without changing its code. Calls are signed, retried, and run once: the guide.
math, stats and vec give Python's answers on every core. For the rest, a .qwer file is Rust, called like any function: the page, and plugins to download.
quillo app runs the same program in a native window, with the platform's own web view.
0.1m + 0.2m is 0.3m. Decimals stay exact from the database to the page and back, and mixing one with a float is an error quillo check finds: the guide.
money keeps amounts in their currency's minor units, never adds two currencies, splits a sum without losing a cent and writes it as each locale does: the guide.
idempotent gives a request sent again with the same key its first answer, with the work and the answer in one transaction: the guide.
db.transaction({ isolation: "serializable", retries: 5 }, f) runs f again when it collides with another transaction, on PostgreSQL, MySQL and SQLite: the guide.
Sponsors
Sponsors pay for the language, the components, the plugins and the docs, and get a say in what comes next.
Get started
$ cargo install --git https://github.com/quillolang/quillo quillo$ git clone https://github.com/quillolang/examples.git && cd examples$ quillo run notes.qwe --watchNeeds Rust 1.94+ and a C compiler: what to install on macOS, Linux and Windows. Then open http://127.0.0.1:8080. quillo check app.qwe finds mistakes without running, quillo repl tries things out, and the VS Code extension (or quillo lsp in any editor) adds diagnostics, hover and completion.
Questions, ideas, something you made? Come say hi on Discord or r/quillo.
Story
quillo install and 628 plugins.idempotent runs once whoever asks, numbers exact or an error, and the latest call wins.