# Gramlot orientation: the exact Pages used in the videos

Recorded with Gramlot **0.3.8**, Python adapter **0.2.12**, and JavaScript
adapters/create **0.2.15**. Python 3.11+; Node 22+ for the optional Inspector
and the JavaScript alternative. Commands below use a macOS/Linux terminal.

## Run the Python examples

```sh
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
cp stages/01_hello.py pages/index.py
GRAMLOT_DEV=YES uvicorn app:application --port 8272
```

On Windows, activate with `.venv\Scripts\Activate.ps1` in PowerShell,
set `$env:GRAMLOT_DEV='YES'`, use `Copy-Item` instead of `cp`, then run
`uvicorn app:application --port 8272`.

Open http://127.0.0.1:8272. To try a later step, copy its file from `stages/`
to `pages/index.py` and reload the browser. `GRAMLOT_DEV=YES` lets the server
reread the Page on each request. Stop the server with Ctrl+C.

The first video also demonstrates the standard initial scaffold:

```sh
gramlot uvicorn new hello
cd hello
uvicorn app:application --reload
```

Before starting Uvicorn, replace that scaffold's `pages/index.py` with
`stages/01_hello.py` and save. Wait for the server to start, then open
http://127.0.0.1:8000/. For the change to `stages/01_welcome.py`, save the file,
watch Uvicorn automatically restart the application, wait for startup to complete,
then refresh the browser. Leave the server running: there is no manual stop or
restart in this sequence. `--reload` watches source changes but does not
automatically refresh the browser. This recording does not use `GRAMLOT_DEV`.
The installed Gramlot CLI creates projects and launches galleries;
it does not provide a general `gramlot server` command. The companion JavaScript from the scaffold is not
needed by these two simple Pages. The downloadable teaching host adds the
standard published collections for later examples.

## Lesson 02: Data, pointers and border layout

Use this downloaded orientation project in the activated environment above;
its host registers the published layout components. Start with
`stages/01_welcome.py` as `pages/index.py`, then run:

```sh
uvicorn app:application --reload
```

Open http://127.0.0.1:8000/. Follow these literal stages in the video:

1. `02_data.py`: initialize `demo.message` with `dataSetter` and bind the heading.
2. `02_message.py`: put a live input inside its visible Message label.
3. `02_pointers.py`: initialize `demo.color`; bind the heading attribute and
   a text input. Try the CSS colour names `crimson` and `seagreen`.
4. `02_border.py`: move the same controls into top/left/center border regions.
5. `02_layout.py`: initialize and add name, email and quantity fields.

After each source change, save, wait for automatic server reload, and refresh
in the browser. Typing into the live inputs changes Data immediately; it does
not edit Python, restart the server or refresh the browser. The label contains
its input; no extra identifiers are needed. The recording uses the same animated
workspace as lesson 01, including typed edits and a visible reload transition.

## Lesson 03: optional Inspector

From the downloaded orientation folder, with the virtual environment activated,
install the optional published Inspector before starting this teaching host:

```sh
npm install --prefix tools @gramlot/gramlot@0.3.8
cp stages/03_inspector.py pages/index.py
uvicorn app:application --reload
```

Open `http://127.0.0.1:8000/`, then click **Open Inspector**. This optional
host connects the real tool to `window.gramlot`; it is development infrastructure
outside the teaching Page. The recording enlarges the Inspector beside the same
live page without recreating its controls.

This Page continues lesson 02 with a compact border container and a Notes
section. `node_label` identifies page, layout, header, greeting and notes in
Source. The `note` attribute on `demo.message` demonstrates that attributes are
separate from the node value.

1. In **Data**, expand `demo` and select `message`. Change **Value** to
   `Hello from Inspector`, then press Enter. Both heading and Message input follow.
2. Change **note** to `Metadata, not the greeting`. The greeting stays unchanged.
3. In **Source**, inspect `main.page.layout.header.greeting`: its value is the
   pointer `^demo.message`, and its color attribute is `^demo.color`.
4. Add an HTML `p` child to `page`, then set its value to
   `Created in the Inspector` and press Enter.
5. Drag that paragraph into `notes`. Add the `style` attribute
   `color: crimson; font-weight: bold` and confirm with Enter.

Runtime edits do not rewrite the Python file. Put the declarations into the
saved Page if you want the result to survive a reload.

## Lesson 04: paths and dataFormula

From the downloaded orientation project, in the activated virtual environment:

```sh
cp stages/04_absolute.py pages/index.py
uvicorn app:application --reload
```

Open `http://127.0.0.1:8000/`. Follow these source stages, saving each change,
waiting for automatic server reload, then explicitly refreshing the browser:

1. `04_absolute.py`: Price and Quantity use `^order.price` and `^order.quantity`.
2. `04_relative.py`: the section has `datapath="order"`; local initializers and
   inputs use relative paths. Change Price to 15 and compare both price rows.
3. `04_named.py`: `nodeId="orderForm"` establishes the named origin for
   `^#orderForm.price` outside the section. Change Price to 18.
4. `04_paths.py`: `formId="orderForm"` and `_anchor=True` establish the origins
   for `^#FORM.price` and `^#ANCHOR.price`. All five rows resolve to `order.price`.
5. `04_formula.py`: add the positional formula and a heading bound to `^.total`.
   Price 12 × Quantity 3 gives 36. Change Price to 20 for 60, Quantity to 4 for 80,
   then Quantity to 5 for 100. Live input changes require no save or refresh.

`nodeId` is introduced for the named symbolic origin, not for recording.
The caret makes an input reactive; the leading dot resolves it in the enclosing
data context. A symbolic path starts from its established Source origin.

The destination and expression come first in `dataFormula`, followed by named
reactive inputs. `_init=True` requests the initial calculation. The result is a
separate Data value read by the heading. This local teaching host permits inline
JavaScript expressions. The generated production scaffold uses a strict Content
Security Policy and named `Logic` methods; use the corresponding authoring form
when moving the example into that host.

## Lesson 05: endpoints and Source

Start with `stages/05_initial.py`, then follow `05_rpc.py` and `05_server.py`.
Copy the selected stage to `pages/index.py`, save, let Uvicorn reload and refresh
the browser. The video types these same changes in its editor.

`05_rpc.py` adds a button calling `with_tax`, exposed with `@endpoint`.
`price="=.price"` samples the current input on click; `result_path=".gross"`
stores the response in Data. The heading reads `^.gross`. Click with Price 100
to see 122; change Price to 200 and the result remains 122 until the next click,
which returns 244. The multiplier is only an illustrative calculation.

`05_server.py` adds `details.remote("product_details", product="^.product")`.
The `@source` method builds a heading and paragraph through its root argument.
The initial lamp choice loads Desk lamp. Click Calculate to show 122, then
choose Notebook and Desk lamp: only the remote details change, while the Price
input and returned Data stay in place. The caret parameter requests new Source
when the product changes; these interactions do not rewrite the Python file.

The example deliberately exposes simple demonstration methods. These methods
need a running Python server and cannot execute from standalone HTML.
Application authentication and authorization belong to the full application.

## JavaScript and standalone HTML

The `javascript/` folder contains the actual small Page and Node host used in
lesson 01, with pinned package versions. Run `npm install`, `npm start`, or
`npm run build`. Save `index.js` before starting Node, then explicitly open
the address printed in the terminal. The build writes `index.html`; stop Node
and open that file locally using the browser's Open File command. The browser
address now begins with `file://`, rather than `http://`.
This Hello world build was checked offline. External resources or server calls
would require their own connectivity.

## Recording

The video shows real browser interactions with these Pages and the published
Inspector. Lesson 01 shows commands as they execute, with the terminal beside
a live capture of an actual browser viewport, including local-file navigation.
Learning goals appear on the right until the first Open, then the browser takes
their place. The large terminal and editor alternate on the left, with animated
typing. Commands and real output remain together in a scrolling history.
Python, Node and build use separate terminal sessions; the Node server keeps
running while the build is executed in the second JavaScript terminal. Visible transitions mark Open and Reload while actual navigation runs.
Narration pauses when needed for real command completion. Lessons 02–05 use
edited captures and hold views during explanation. The editor and browser
controls are recording infrastructure, not Gramlot components. English narration is synthesized with
Kokoro; captions and a transcript accompany each video.

## Reading the teaching code

Hello world needs only `root.h1("Hello world")` inside `Page.main`. There are
no IDs added for the recording tests. Remaining HTML IDs connect labels to
their input controls. Readable Source node labels and the demonstration `note`
attribute are introduced in lesson 03, when the Inspector makes them useful.
Lesson 04 deliberately introduces `nodeId`, `formId` and `_anchor` to explain
symbolic paths. Recording automation locates headings, controls and visible text.
