SQLite as a payload
A SQLite database file is a compact, typed, self-describing payload — often a better wire format than JSON. Serve the .sqlite file directly and read it in the browser with QIP components that weigh 10–21 KB, instead of shipping the 849 KB official engine for read-only work.
The same bytes stay compatible with the official sqlite3.wasm, so an app can render instantly with a tiny reader and lazily upgrade to the full engine only when someone needs SQL or writes. The comparison below proves both readers return the identical result.
Browse a database #
This lists every table with its columns and declared types. The database arrives like any other asset: a <source> element pointing at /data/countries.sqlite (48 KB).
<qip-edit>
<source name="input" src="/data/countries.sqlite" type="application/vnd.sqlite3" />
<source src="/components/application/vnd.sqlite3/sqlite-schema.wasm" type="application/wasm" />
<output name="output"><pre><code></code></pre></output>
</qip-edit>
The <source name="input"> element is the input and the wasm <source> is the pipeline. The input's type attribute must match the component's declared application/vnd.sqlite3 input type.
Any table to CSV #
The Titanic dataset (68 KB) holds eight tables. Pick one and sqlite-table-csv.wasm (19 KB) converts it to CSV, entirely in your browser.
Uniforms come from ordinary form controls: the <select name="uniform-table"> feeds the component's uniform_set_table export, exactly like ?table=N on the CLI.
Point lookup by rowid #
sqlite-row-lookup.wasm (21 KB) descends the table's b-tree instead of scanning it — it touches a handful of pages to fetch one row out of 891.
Bring your own database #
Drop any SQLite file here and browse its schema. Nothing is uploaded: the file is read locally into the component's memory. Until you choose a file, the preview falls back to the countries database.
Databases should be published with VACUUM INTO 'payload.sqlite' — that guarantees a single clean UTF-8 file with no WAL sidecar and no freelist bloat. The readers deliberately reject WAL-mode and UTF-16 files with a clear error rather than risk stale or garbled reads.
Same result, much less to load #
Both readers below convert the Titanic Observation table (891 rows) to CSV: the 19 KB QIP component, and the official 849 KB sqlite3.wasm running SELECT *. The outputs are compared byte for byte.
| Phase | QIP component | Official sqlite3.wasm |
| Download (uncompressed) | | |
| Compile + instantiate | | |
| Open database (68 KB) | | |
| Read table → CSV (891 rows) | | |
| Total | | |
The official engine remains the right tool for SQL queries, joins, and writes. The point is sequencing: readers this small make it practical to treat .sqlite as a first-class response format, then load the full engine only for the minority of sessions that edit.
CLI equivalent #
go install github.com/royalicing/qip@latest
qip run modules/application/vnd.sqlite3/sqlite-schema.wasm -i mydb.sqlite
qip run modules/application/vnd.sqlite3/sqlite-table-csv.wasm '?table=1' -i mydb.sqlite > table.csv
qip run modules/application/vnd.sqlite3/sqlite-row-lookup.wasm '?table=0&rowid=42' -i mydb.sqlite
qip run modules/application/vnd.sqlite3/sqlite-table-count.wasm -i mydb.sqlite
These modules expect application/vnd.sqlite3 input. The CSV converter outputs text/csv, so it composes with any downstream CSV component.