Gramlot
Describe application interfaces in Python; let a JavaScript runtime handle interaction in the browser. Gramlot's model connects a declared interface (Source) to structured application state (Data Bags), using bindings, controllers and reusable components.
Gramlot is intended for Python developers building interactive forms, data tools and application interfaces. Server adapters connect it to a web server; the core is independent of server and database technology.
Release status. The current release is 0.2.20, published on PyPI (
gramlot), on npm and JSR (@gramlot/gramlot) and as the GitHub release v0.2.20. 0.2.0 (HTML/SVG data binding), released on 2026-09-30, was qualified on Chromium, WebKit and Firefox and accepted by the owner; the patch releases that follow it keep its contract.
JavaScript package
The JavaScript distribution is @gramlot/gramlot, on npm and on JSR. Install it with
npm install @gramlot/gramlot or npx jsr add @gramlot/gramlot.
Node.js 22 or later and Bun are supported server runtimes; the browser runtime
is bundled separately. The core provides server, gramlot-server, page and runtime.
Standalone startup, WorkerHost and WorkerTransport belong to @gramlot/gramlot-serverless
(in the gramlot-js-server repository).
Python pages require the Python distribution and a Python server.
A page is a module in the pages folder that exports a Page subclass. GramlotFileServer
serves that folder; an adapter passes each request to the server:
// pages/hello.js
import {Page as GramlotPage} from '@gramlot/gramlot/page';
// GramlotFileServer reads the export named `Page`.
export class Page extends GramlotPage {
static title = 'Hello';
main(root) {
root.div('Hello from Gramlot', {id: 'greeting'});
}
}
// server.js
import {GramlotFileServer} from '@gramlot/gramlot/server';
const server = new GramlotFileServer('./pages');
const {pageId, html, nonce} = await server.openPage('hello');
// Answer the browser with `html`; it then sends its envelopes to `POST /gramlot/rpc`,
// which the adapter answers with `server.call(text, {owner})`.
The example pages and their gallery are the separate package gramlot-examples.
Can I use it today?
- Python:
pip install gramlot. - JavaScript:
npm install @gramlot/gramlotornpx jsr add @gramlot/gramlot. - Archives: each GitHub release
carries the wheel, the sdist, the npm package of
js/andSHA256SUMS. - Adapters:
pip install "gramlot-py-server[uvicorn]"(alsodjango,flask,fastapi,kajenn) for Python pages;npm install @gramlot/gramlot-js-server(Node.js and Bun) or@gramlot/gramlot-serverless(no server) for JavaScript pages;npm create @gramlot page|sitestarts a JavaScript project.
For updates, follow Updating an existing installation: packages, source builds, restart/export and verification.
For a first look, use Try Gramlot: the quick route: choose Python, Node.js or serverless, open the gallery, then create your own page. It also explains how to install the optional Chrome DevTools extension. Continue with the learning route and Writing pages. The broader experimental implementation remains in gramlot-poc.
Gramlot 0.2.0
0.2.0 adds HTML/SVG data binding to the Gramlot core. The DOM depends on the Source and the Data; Data changes reach the DOM, and native controls write back.
dataSetter(destination_path, value=None, **attr)writes initial Data values, replacing the legacydata(path, value); the HTML5<data>element ishtml_data(...);^,=and==pointers, relative, symbolic and?attrpaths, variable datapaths;dataFormulaanddataController, with named logic as the primary path (since 0.2.5 theLogicclass exported by the page modulefoo.js, besidefoo.pyfor a Python page, orclass Logicinfoo_aux.js) and inline code only under a permissive Content Security Policy (a clear error under a strict one);- native controls bound with
value='^path',live, checkbox and radio groups,visible, reactivestyleandclass, bound SVG attributes, freeze and thaw; - buttons with a nested
dataControllerandconnect_on<event>; - a minimal
GramlotServercontract (resolve_page,resolve_resources,open_pagewith a mount prefix) withGramlotFileServeras reference; pages keepPage.cssand same-name companions (foo.css, andfoo.jsorfoo_aux.jsfor the logic).
Examples: the families binding and
controllers of
gramlot-examples, each page in Python with its
JavaScript equivalent. Writing pages and
Classes and server adapters describe the
contract, its exclusions and the differences from legacy GenroPy. Components start
with 0.3.0.
Start here
-
Try Gramlot: the quick route — choose an environment, try three examples and create a project with its CLI.
-
The Gramlot family — what Gramlot is, the core and the adapters, and which one to choose.
-
Is Gramlot a fit? — the development model and its current limits.
-
Try Gramlot — the complete learning route, in release order.
-
Tests and coverage — what the badges mean and why JavaScript coverage matters.
-
Classes and server adapters — repository map and responsibilities.
-
Writing pages — release-by-release authoring: HTML/SVG, binding, data exchange, RPC and remote.
-
Themes and CSS — Python examples, complete variable and class catalogues, light/dark customization and practical styling advice.
-
Extending Gramlot — current extension points and contracts still to define.
Project status
The tests badge reports the Core tests workflow on main (Python and
JavaScript suites and the browser checks in Chromium); the documentation badge reports the documentation
checks. Coverage is collected by the same workflow and reported on Codecov per
runtime: JavaScript (every file of js/src, including files no test imports) and
Python (src/gramlot), never merged into one figure. See
Tests and coverage.
Maintainers keep architecture decisions, port reviews and concise working documents
in the repository, outside the public user manual. Public source files remain
readable on GitHub. New work starts from develop; main is the consolidated
reference. Gramlot is licensed under Apache 2.0.
Integration repositories
Environment-specific adapters and setup instructions live in two repositories:
- gramlot-py-server (PyPI
gramlot-py-server) serves Python pages. One package holds five adapters, one extra each:uvicorn(any ASGI server),django,flask,fastapiandkajenn. Its commandgramlot <environment> new|gallerycreates a project or serves the gallery. - gramlot-js-server serves
JavaScript pages with three npm packages:
@gramlot/gramlot-js-server(Node.js and Bun, commandgramlot),@gramlot/gramlot-serverless(pages in a browser Worker without a server, commandgramlot-serverless) and@gramlot/create(npm create @gramlot page|site).
The example pages and the gallery are in
gramlot-examples. The earlier
adapter repositories (gramlot-uvicorn, gramlot-django, gramlot-fastapi,
gramlot-flask, gramlot-kajenn, gramlot-serverless, gramlot-minimal) are
archived. See the ownership contract.
The published 0.1.0 archives keep their original names.
Reusable application index and installable root shows Python-first authoring, a custom footer, iframe tabs and the root manifest.
Development work on publish/subscribe, authored references and native ask is documented in the authoring guide. This is not a release announcement.
Metadata
Release files for gramlot 0.2.20
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gramlot-0.2.20.tar.gz | 530.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gramlot-0.2.20-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / gramlot-0.2.20.tar.gz
| Download URL | gramlot-0.2.20.tar.gz |
|---|---|
| Size | 530.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5024986338426ef2a28f6875096e8fa8e0f1c76dc594e9b1416fccafe2668230
|
|
BLAKE2b-256 checksum How to use checksums |
26ceb93f3a0eede06615a1311a40b5d2117017aeaaa96416c40caa37dc352d6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / gramlot-0.2.20-py3-none-any.whl
| Download URL | gramlot-0.2.20-py3-none-any.whl |
|---|---|
| Size | 588.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f98111d54ea115adf33fd6d7a82788679231658901c57d41ee1cbace359e840a
|
|
BLAKE2b-256 checksum How to use checksums |
5351c0365fa42b1ba25fcc34f0c3f17080fe99a72fb76af00b240ca63002297c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log