Guide

Introduction

Everything Quillo does, and how: the language, components, routes, the standard library, databases, services, and running it. For what Quillo is and why, see the README. For what it does not do, and what to do instead, see Possible or not.

Quillo is a single binary, built with Cargo:

cargo build --release./target/release/quillo new hello                        # a program to start from, in hello/./target/release/quillo run app/main.qwe --watch        # the sample app: http://127.0.0.1:8080./target/release/quillo check app.qwe                    # find mistakes without running./target/release/quillo build app.qwe                    # build its Rust (.qwer files) beforehand./target/release/quillo repl                             # try code line by line./target/release/quillo lsp                              # language server (for editors)./target/release/quillo dap                              # debugger (for editors)cargo test

This guide is for Quillo 0.8.0, and CHANGELOG.md says what it changed. Features marked (since 0.7) came in 0.7.0. On an older release, read that release's guide: https://github.com/quillolang/quillo/blob/v0.7.0/USERGUIDE.md or https://github.com/quillolang/quillo/blob/v0.6.0/USERGUIDE.md.

Options of quillo run

quillo run checks the program, executes its top level and, if it declared routes or server fns, serves them; a program with neither ends when its top level has run (under --watch it is served all the same). The program is the first argument that is not an option, wherever it stands (quillo run --watch main.qwe works); left out, or given a folder, it is that folder's main.qwe, so quillo run in a program's folder runs it. quillo app.qwe alone is quillo run app.qwe.

Options are words starting with -- that you add to the command line when you start the program, and they hold for that run only; nothing is written to a file:

quillo run main.qwe --watch                          # while you work on itquillo run main.qwe --port 8081 --max-body 50MB      # in production, on another port, larger uploads

An option's value follows it, or = (--port 8081, --port=8081); -w is the one short option (-p is not --port); -h prints the usage; a mistyped option is told the nearest one there is. quillo app, quillo serve and quillo fcgi take these options too, but for a few each refuses (below). The options, and when to give them:

OptionWhat it does, and when to give it
--port N, --host Hwhere to listen (default $PORT or 8080, on 127.0.0.1). Give --port when 8080 is taken or a host names the port; --port 0 takes any free one (platform().server.port says which). Give --host 0.0.0.0 to be reached from other machines without a proxy in front; --host localhost is 127.0.0.1
--listen unix:PATH (since 0.7)listen on a Unix socket instead of a TCP port, when a web server on the same machine passes requests on (on a shared server, so the neighbours cannot reach the port): made with mode 0600, removed when the server stops, and at most 100 bytes long (a short path relative to the folder quillo runs in). A $PORT that holds an absolute path (/home/u/app.sock, or unix:/home/u/app.sock) is taken the same way. Not with --split, --instances, --register or --join (see Quillo on a shared server)
--socket-mode 660 (since 0.7)with --listen: the socket's permissions, in octal, when the web server reaches it through the owner's group; the owner must keep read and write (600, the default)
--watch, -wwhile you work on the program: reload when it or a used file changes (a symbolic link pointed elsewhere, to a file or a folder, counts, within a second), show errors on the page, and refresh open pages; a file the program served with file() that changes refreshes them too, and a stylesheet is swapped in them as they are, keeping what they show (for one another tool writes, such as Tailwind's). Started, or reloaded, while a file is broken or missing, it watches every file that load read or tried and the folders of those not there, so fixing or making one loads the program; each error is said once. Not in production
--reloadin production, for a program whose files change while it runs (a deploy that copies new files, a plugin editor): reload when files change, with no errors shown on pages and no page refreshes; with --instances, each instance loads the change, the first checking it, so one that does not check reaches none; --split passes it to its services
--env-file Fwhen the settings are not in the .env beside the program: a file kept outside the site's folder, or one file per place (--env-file prod.env); a path from the folder quillo runs in, which must exist
--policy FILE (since 0.7)before a deploy, or on a server you share: narrow what the program may do, after /etc/quillo/policy.toml and before the quillo.policy beside it; may be given more than once (see The policy)
--no-build (since 0.7)on a server with no Rust, or one that must never run cargo: load only libraries quillo build made, as .quillo/plugins.lock names them (see Rust)
--no-checkwhen the program is known to check (a deploy that ran quillo check already) and starting must be quick: skip the static checks
--max-body Nwhen visitors send larger files or bodies than 10MB: the largest request body to accept, a size such as 50MB (KB, MB and GB, in any case, are 1024-based) or bytes; default 10MB; a larger body gets 413 (see Uploads)
--max-compute 2s (since 0.7)when a request that computes for long must not hold up the others: end one that computes this long without letting go, as a 500 (see Concurrency)
--workers Nrequests that can wait at once (for a database, the network), each on a thread (default 64). Give fewer where an account limits its threads (shared hosting), more for many slow calls at once
--instances Nto use N cores on one machine: run the program N times over, one event loop each, each with its own variables (see Concurrency); not with --watch, --register or --split; more than the machine's cores is warned of
--trust-proxy 10.0.0.0/8 (since 0.7)when a proxy (limer, nginx, Apache) is in front: believe X-Forwarded-For from these addresses, so request.ip and the limits per client are the visitor's (see Live data)
--live-per-client N (since 0.7)when one address is many visitors (an office behind one address): the pages one client may have waiting for live data (default 256)
--plain-httpwhen the site is served over plain HTTP on purpose, on a network you trust (a factory's kiosks at http://10.0.0.5:8080): cookies are not Secure, which browsers would drop there (see Cookies and sessions)
--allow-path DIR (since 0.7)when a script used as a tool must read or write files outside its folder, or a deploy links a folder from elsewhere (uploads -> /srv/shared/uploads): read_file and write_file may use DIR too; any part of the program may then, routes too (see Paths and links)
-- a b (since 0.7)for a script: after the program, what follows is the program's, and args() gives ["a", "b"]; before it, -- ends the options (quillo run -- a.qwe x). A stray word elsewhere is told it goes after -- (see Scripts as tools)
--with CMDwhen a tool must run beside the program while you work (Tailwind's watcher): run a command (through sh -c, in its folder), its lines marked with its name, stopped with it however it ends, a Ctrl-C or SIGTERM while it loads, a panic and a SIGKILL too (more than once for several): --with "npx tailwindcss -i src/app.css -o public/app.css --watch"
--log Fthe request log on stderr: text (the default), json (one object per line) for a log collector, or off when another layer logs requests (see Logs and metrics)
--metricswhen Prometheus (or another scraper) should read the server: answer GET /_quillo/metrics (see Logs and metrics)
--query-stats (since 0.7)to find slow queries on a running server: time database queries for GET /_quillo/health/queries, the last 100, overall and per statement (on under --watch; see Stopping and health)
--describewhen a gateway imports the program's API: answer GET /_quillo/describe with it, as quillo docs writes it (see The program's API)
--no-view-cacheto measure, or to rule the cache out while looking for a bug: render views every time (see Cached views)
--no-jobson all but one of several servers that do not share a database, or on a copy that must not run them: run none of the program's scheduled jobs here (see Scheduled jobs)
--no-prefetchwhen links must not be fetched before they are clicked (to measure, or a site whose GETs are counted): turn prefetching off (see Prefetching)
--base PATHwhen a proxy serves the program under a path (/shop) and takes the path off before passing a request on: the program sees /x for /shop/x, and its links and redirects carry the prefix (/y is written /shop/y)
--splitto try the app as separate processes, as it will run deployed: run each service as a process of its own (see Services); with --port 0, the services are told the port the app was given
--scale NAME=Nwith --split, for a service that needs more than one process: run service NAME as N copies (1 to 64), called in turn (see Services)
--service-url NAME=URLwhen service NAME runs on another machine: where it is (also QUILLO_SERVICE_<NAME>, the name in capitals); several addresses, comma-separated, are taken in turn (see Services)
--as-serviceto run a service on a machine of its own: serve the program as a service, its server fns answering other services' signed calls, not pages (see Services)
--service-name NAMEwith --as-service, when the file is not named as callers call the service: the name it answers to; calls signed for another service are refused
--join URLwith --as-service and a --port, to add a copy of a service while the app runs: join the app at URL, signed with QUILLO_SERVICE_KEY when it is set (see Copies that join)
--join-as URL (since 0.7)with --join, when the app must call the copy at another address than the one it connects from (https://billing-3.internal:8443); it must lead to where the copy joined from
--no-join, --allow-join A,B (since 0.7)on the app, to take no copies that join, or only copies of these services
--register URL, --service Sto run several servers behind limer: join its pool at its admin address (the pool named S, else the file's name), and share live updates with its other servers; needs LIMER_ADMIN_SECRET (see Several servers)
--wt-port Nwhen the UDP port of the HTTP port's number is taken or not open: the UDP port pages connect to over WebTransport (see Channels)
--tls-cert F, --tls-key Fwhen WebTransport should present a real certificate, instead of one of its own; the files must exist, go together and be a pair (--tls-cert b.pem and --tls-key a.key are no pair: the key is not the certificate's); given twice, the last wins
--no-wtwhen UDP is blocked between pages and the server: no WebTransport, so pages' channels and streams use a WebSocket at once

Other commands

quillo new <folder> (since 0.7) writes a program to start from. By default it is the to-do app, the eight files of app/: a database with a migration, a component, files served. --minimal writes three: main.qwe, lib/greet.qwe and ui/page.qwe, a page, a component and a function both sides use. Both get a .gitignore (*.db, *.db-wal, *.db-shm, .env, .env.*, .quillo/), and --binary copies this quillo into <folder>/.quillo/bin/quillo. It refuses a folder that is not empty (an empty one, or one holding only .git, is used) and a name Windows refuses (con, aux, nul, prn, com1 to com9, lpt1 to lpt9, any of <>:"|?*\, a trailing dot or space, a line break). A new folder is written beside the target and moved in place at the end, so a failed new leaves nothing half made, and it never writes an empty folder; an empty folder that is there is built inside, so its parent need not be writable (a leftover of a new whose process is gone is removed). It warns when the folder is inside another program, and prints the next step:

quillo new hello --minimalcd hello && quillo run --watch

In VS Code, Quillo: New program (extension 0.14.0) asks for the to-do app or the minimal one and for a folder, runs quillo new and opens the folder.

The other commands: quillo check (below, and Checking), quillo docs (the API as OpenAPI 3, to stdout; see Services), quillo build (the Rust files; see Rust), quillo fix (since 0.7) (the import lines a program's files need, and 0.6's lines turned around; see Files of a program), quillo serve <folder> (since 0.7) (a folder of files as they are, as a static host serves it; see Static files), quillo classes <file.qwe> (since 0.7) (the classes the program's markup writes, one a line; see HTML literals), quillo fcgi <file.qwe> (since 0.7) (the program behind FastCGI, for mod_fcgid or nginx's fastcgi_pass; see Quillo on a shared server), quillo repl, quillo lsp, quillo dap, quillo version (or --version, -V), which names the commit: from a source archive it reads the COMMIT file git archive writes, else says (commit unknown). quillo <file.qwe> is quillo run <file.qwe>, options and all, whatever the case of its extension (quillo MAIN.QWE). A misspelt command is told the nearest (unknown command `chek` (did you mean `check`?)), and a file of another extension given with no command is told how to run it (to run the file: quillo run tool). An option given before the command is told where it goes, in one line: quillo: put the command first: `quillo run --watch main.qwe` . -h and --help are read first, after any command (quillo run -h with no program, quillo lsp --help), and print to stdout. quillo run given a file that is not a program says what it is and how to serve it: page.html is HTML, not a Quillo program: serve its folder as it is with `quillo serve .` , and the same for Markdown (with markdown_page), Rust (use "t.rs"), and .css, .js, .json, .txt, .xml, .csv and .svg files (file()); a folder with no main.qwe but an index.html is told quillo serve. check, docs, build and fix take one program, and refuse a second and an option they do not have (check has --strict-null and --policy FILE). quillo check exits 1 when there is an error (warnings do not fail it), quillo run 1 when the program does not load or the port cannot be taken, and either 2 for a usage mistake (an unknown option, an option without its value, no program, --register without its secret, options that do not go together, a --port outside 0 to 65535, a --tls-cert or --tls-key file that is not there, a policy file that cannot be read or says something a policy does not say, a .env that cannot be read). An option that takes a value refuses another option in its place: --service-name --watch says needs a value, and --watch is an option. A stopped server exits 0 (see Stopping and health).

Their options, given after the command as quillo run's are:

Command and optionWhat it does, and when to give it
quillo check --strict-nullto find where a value may be null and null does not work (see Checking); check only, not run
quillo check --policy FILE (since 0.7)before a deploy to a server with a policy: check the program as it would run under it (see The policy)
quillo new --minimal, --binarythree files instead of the to-do app; a copy of this quillo in the new folder, for a machine that has none
quillo app --open PATHthe page the window opens on (/ by default); app takes run's options but --host, --register, --service, --port and --listen: its window asks the program directly, with no socket (see Desktop apps)
quillo serve <folder>run's options, such as --port (see Static files)
quillo fcgi <file.qwe>run's options but --split, --instances, --register and --join; --listen unix:PATH or --port when no FastCGI manager hands it a socket (see Quillo on a shared server)
quillo install --example, --update, --list [word], --force, --dir DIR, --registry URLa plugin's example program too; the plugins here the catalog has newer; what the catalog has; replace a file changed by hand; install elsewhere; another catalog (see Plugins from the catalog)
quillo repl -ikeep the greeting and prompts when the input comes from a pipe (see The REPL)

quillo build, docs, fix and classes take a program and no options.

Settings and the environment

The .env beside the program is read into its environment as it starts: KEY=value lines (export allowed, # for comments, and # ends a bare value, so KEY= # set me is "" while KEY=#fff is #fff; values in "..." take \n, \t, \" and \\, and '...' is as written; a quoted value goes on to its closing quote across lines, as a PEM key does, and a quote never closed skips its own line only; a byte-order mark at the start is skipped; a key is letters, digits and _, and a line that is not KEY=value, or whose value holds a NUL byte, is skipped and said at the start: quillo: .env:3: not KEY=value, skipped), for env("API_KEY") and for Quillo's own settings (PORT, QUILLO_SECRET). Only a .env that is not there (or a folder of that name) is nothing: one that cannot be read, is not UTF-8, or is a link to nothing stops the start with exit 2, saying where and the ways out (quillo: cannot read .env: it is not UTF-8 text: byte 0xE9 at line 1, column 9 (save it as UTF-8); to start without it, remove it or give `--env-file /dev/null` ), as a missing --env-file does, and a service's own .env stops its load the same way. A variable the environment already has wins, so a .env left on a server cannot override what production sets. It is read once: a program started with --reload does not read it again when its files change. Another file is named when the program starts: quillo run main.qwe --env-file /etc/shop/prod.env. A service reads the .env beside its own file as well, in one process and under --split alike: its values come before the app's file's (the app's reach it too), and after the environment's. Keep .env out of version control.

Everything Quillo reads from the environment:

Variable
PORTthe port, when --port is not given; an absolute path is a Unix socket to listen on, as --listen unix:
QUILLO_SECRETsigns sessions (see Cookies and sessions); without it, a key made at start
QUILLO_QUERY_STATS (since 0.7)1: query stats on from the start, as --query-stats
QUILLO_HEALTH_TOKEN (since 0.7)lets a request with Authorization: Bearer <it> see each statement's query stats and switch them on or off; 16 characters at least
QUILLO_DBthe database when the program does not call db.open; without it, SQLite in memory, gone at restart
QUILLO_SYSTEM_DBwhere Quillo's own tables go with a database per tenant (see Quillo's own tables)
QUILLO_SERVICE_SECRET, QUILLO_SERVICE_<NAME>signs calls between services (several, comma-separated: the first signs, any is taken); where service NAME runs (see Services)
QUILLO_SERVICE_SECRET_PREVIOUS (since 0.7)a secret still taken while QUILLO_SERVICE_SECRET is changed (see Authentication between services)
QUILLO_SERVICE_KEY (since 0.7)a service's own key: a copy joins with it, and it proves the copy is that service (see Copies that join)
HTTPS_PROXY, HTTP_PROXY, ALL_PROXY, NO_PROXY (since 0.7)the proxy http.* calls go through, and the hosts that do not (see HTTP client)
LIMER_ADMIN_SECRETfor --register (see Several servers)
QUILLO_NATIVE_CACHE, CARGOwhere .qwer files are built, and with what (see Rust)
PUBLIC_...any such variable may be read in a component (see What the browser can reach)
QUILLO_CHROME, QUILLO_TEST_PG_BIN, QUILLO_TEST_MYSQL_BIN, QUILLO_TEST_LOG, LIMERcargo test: where Chrome, PostgreSQL, MariaDB and limer are; show the test servers' output

The one other configuration is the policy, which only takes away: /etc/quillo/policy.toml, --policy FILE and quillo.policy beside the program (see The policy). HOST is not read (--host is), and RUST_LOG and NO_COLOR do nothing. The program's paths (use, db.open, read_file, .env, quillo.policy, quillo-system.db, .quillo/native) count from the program file's folder, whatever folder quillo was started in.

Desktop apps

quillo app runs a program in a native window instead of a browser tab: the platform's own web view (WebKit on macOS and Linux, WebView2 on Windows) shows its pages, and closing the window ends the program. It is built only on request:

cargo build --release --features app      # Linux also needs libwebkit2gtk-4.1-dev and libgtk-3-dev./target/release/quillo app app/main.qwe --watch

The release downloads are built without it. It takes the options of run except --host, --register and --service, reads the .env beside the program (or --env-file) as run does, keeps --with commands going until the window closes, and takes --open PATH, the page the window opens on (quillo app main.qwe --open /admin; / by default). The program runs in the window's process with no HTTP server: nothing listens, and nothing else on the machine can reach it. The window asks for its pages through a scheme of its own, quillo://app/ (https://quillo.localhost/ on Windows), and the program answers each request as a server would, so routes, sessions, server fns, uploads and live data work as in a browser (Phone apps, below, says what differs). The origin is the same at every launch, so what a page keeps in localStorage and IndexedDB is there at the next one. The web view keeps no cookies for the scheme, so the program's are kept for it in .quillo/app-cookies.json beside the program, and its session key in .quillo/.quillo-secret unless QUILLO_SECRET is set: someone signed in stays signed in from one launch to the next. --port and --listen are refused, as there is no socket to give them to. Links to other sites open in the system's browser. Only macOS has run this way; Windows and Linux take the same code through wry, not yet run.

Editor support: quillolang/editors has a VS Code extension (highlighting, diagnostics as you type, quick fixes, hover, go to definition, completion, outline, snippets, end tags added as you type a start tag's > or </, and a debugger: see Debugging), which Cursor, Windsurf and VSCodium take as its .vsix (or from Open VSX, once a release is published there). The same repository has a plugin for the JetBrains IDEs and Android Studio, an extension for Zed, and support for Neovim, Helix, Emacs, Sublime Text and Vim, with Eclipse and Visual Studio set up by hand. All but Visual Studio run quillo lsp, and all but Visual Studio, Sublime Text and Vim quillo dap. Zed, Neovim, Helix and Emacs highlight with tree-sitter-quillo, a tree-sitter grammar in the same repository; documentation sites can use its Shiki, highlight.js and Prism definitions. An element left open is reported at its start tag (`<li>` is never closed: add `</li>` before `</ul>` on line 5), with a quick fix that adds the end tag there. A class in markup (<span.chip>, class="chip") goes to its rules with Go to Definition, in css(...), a component's style or the CSS files under public/, and hover shows them; those classes are offered after <span. and in class=". Find All References lists a class's rules and the markup that writes it, from either side, and Rename renames it in both (a class put together, card-${size}, is left as it is). A class no sheet has a rule for is marked: a warning when a rule's class is close to it (no style sheet has a rule for `.chiip` (did you mean `chip`?), which quillo check says too), else a faint hint, as markup often carries classes for its own sake. Neither is told when the program has no sheets of its own or links one from another site. On a use line, the path goes to its file and completes to the program's files, and the names taken from a .qwer file go to their Rust functions, show their signatures (under the name after as) and complete to the file's functions. Inside a call, as ( and , are typed and with Ctrl+Space, it shows the parameters, the current one marked, and a line about the function: a builtin's own, a .qwer function's /// comment, or the // comment above your function. Completion offers the variables in scope at the cursor first. It runs the quillo it finds (its quillo.path setting, the workspace's target/release, then the PATH), so stale errors on code the build accepts come from an old binary: quillo --version names the commit, and scripts/doctor.sh points out an old one. Other editors can run quillo lsp (hover, go to definition (of names, and of classes to their CSS rules), references and rename of classes (also from the CSS files under public/, when the client sends them), document symbols, completion after ., <, </ and @ (and of classes after <tag. and in class="), diagnostics on open, change and save, quick fixes as code actions, and quillo/closeTag: at a position just after a start tag's > or after </, the text to insert there, or null; initializationOptions: { "strictNull": true } for the extra warnings) and quillo dap directly. The language server reads the editor's text, not the file on disk, and says diagnostics under every URI a file is open by, so a project opened through a link gets them; it reads headers in any case (content-length), answers -32002 to a request before initialize, -32600 after shutdown, and -32700 to a body that is not JSON.

Examples, in quillolang/examples (cloned as ../quillo-examples in the commands here): hello.qwe (routes), orders.qwe (payload-based routing and middleware), todo.qwe (server-rendered app with a JSON API), notes.qwe (SQLite and a live component), scroll.qwe (infinite scroll over 100,000 rows, rendering only a window), compose.qwe (views and components built from each other), layout.qwe (a page described as JSON, with a live editor), spa.qwe (a single-page app: client-side navigation, deep links, 404s), life.qwe (Conway's Game of Life, run by a timer in the browser), storm.qwe (a dashboard under a storm of random changes, tested for leaks), services (a shop that bills through a billing service, in one process or split apart), and index.qwe, which mounts all of them in one server.

Phone apps (preview)

(since 0.7) A program runs inside an iOS or Android app: the runtime is linked into it and runs the program in the app's process, with no HTTP server, as quillo app does on a desktop, so it works offline and keeps its SQLite database in the app's container. mobile/ios/build.sh app --run builds the app around a program folder for the iOS simulator and opens it there, and mobile/android/build.sh app --run a debug APK for an Android emulator or phone. The app's name, id, version, build number, icon and first file (main = "mobile.qwe", by default main/) come from an app.toml in the program's folder; --device and --archive (iOS) and --release (Android, a signed APK and App Bundle) make builds for the stores; mobile/README.md says how, and what a phone build leaves out (compiled numbers, WebTransport, .qwer plugins built at run time, anything that starts a process). The app puts window.quilloNative on the program's pages for what a web view cannot reach: js("quilloNative.location"), .haptic, .battery, .notify, .keepAwake, .brightness, .share, .openSettings, .wait. Both apps answer .share as { shared, to } (on Android both null, as it cannot tell), on Android .brightness(null) gives the screen back to the system (iOS does when the app leaves the screen), and a tel:, sms:, mailto: or maps link opens what the phone opens it with (FEEDBACK28.md, Q-346). It has run on a real iPhone, served on 127.0.0.1 as it was then; the scheme below has run on the iOS simulator and the Android emulator (pages, a server fn, live data, a form with a file, and storage and a session kept from one launch to the next), not yet on a real phone. Uploads to the stores are not done yet, and HarmonyOS NEXT is planned (mobile/harmony/PLAN.md). platform() (see Standard library) tells a program it is in a phone app, and on what. mobile/examples/fieldbook tries the phone's hardware from a program.

Nothing listens. The web view gets its pages from the program through a scheme the app answers: quillo://app/ on iOS (and in quillo app on macOS and Linux), https://quillo.localhost/ on Android (and on Windows). So no other app on the phone, and no page in its browser, can reach the program; iOS has no listening socket to take back while the app is suspended; and the apps carry no exception for plain HTTP (iOS's local-networking ATS key and Android's cleartext config are gone). The origin is the same at every launch, so localStorage and IndexedDB keep what they had. An install made before kept them under http://127.0.0.1:<port>, and they stay there: they are not copied to the new origin (the program's database is the program's, and is not touched).

What a scheme cannot carry goes through the app's message bridge: on Android every request with a body (its interceptor is given none), on WebKit a body that is a file, a Blob or a FormData (it hands the scheme none of those, so the page turns them into bytes first), and everywhere the connections live data and channels keep open. The shell's script, run before every page, hands the runtime its way out when the runtime asks for it with an event, so nothing is put on window. On Android, where every body goes through the bridge, it also takes over the page's own fetch, so a script's own request with a body goes the same way: the one global it changes. A form the scheme cannot carry (every post on Android, a form with a file on WebKit) is sent through the bridge, and the page goes to its answer, as after a post and a redirect. What the program sees is what a server sees, but:

mobile/README.md lists the calls an app makes into the runtime (quillo_open, quillo_request, quillo_bridge and the rest).

Why .qwe?

Quillo files end in .qwe for ergonomics. Q, W and E sit side by side at the left end of a QWERTY keyboard's top row, so the extension is one quick roll of the left hand's little, ring and middle fingers, with no reaching and no looking down. You type it in every quillo run app.qwe, every use "lib.qwe" and every new file name, so it should be the easiest thing in the line to type.

It also reads as what Quillo is for: Quit Worrying about Everything. quillo check finds mistakes before the program runs, text in pages is escaped, cross-site posts are refused, sessions are signed, a payment sent twice is made once, and a transaction that collides is tried again. What it does not take care of is listed in Possible or not, so you know what is still yours to worry about.

Thread
93Useful? Like it, or add to its thread below.

Thread 1 post

On Introduction: questions, tips, corrections, and code that uses it. Read the thread on its own page →

  1. restimguayopened this thread6 d ago

    Everything Quillo does, and how: the language, components, routes, the standard library, databases, services, and running it. For what Quillo is and why, see the README. For what it does not do, and what to do instead, see Possible or not.

    this is nice!

    Edit this page on GitHub · made from the user guide · questions on Discord or r/quillo