Lenso

Create a local Web App

Select the linked Web starter, add a second Web Plugin, and check both routes locally.

Development preview · Not a published framework version

This page does not substitute for an unavailable published version. Check an exact version

Locale
en
Content revision
sha256:2e2476ef39689ac6d1eef3f65416e4739a7e68f6ca927d5fde60b3de69e251a8
简体中文

Published Rust dependencies, source-built CLI. This tutorial builds a matching lenso-cli from the consolidated lenso source. A fresh App outside that checkout resolved its Lenso packages from crates.io without Lenso path or Git overrides, then passed app build, app check, app show, and a real greeting request. That check covers the generated first Web Plugin, not the second-Plugin steps below or an installed CLI binary. The generated app/local.starter/Cargo.toml is the source of truth for exact pins; the generated Host selects its own Web Ingress version. If an exact dependency is unavailable, stop and report its name and version without changing the pins. Public crates do not create a signed Marketplace listing or deploy this Site.

This path explicitly selects the linked Web starter with --web, uses its browser form to make a real POST /greetings request, then adds a second linked Web Plugin. It does not need a Marketplace listing. Human and coding-agent users follow the same commands and completion checks below.

Without --web, app create instead makes a root Cargo Process Plugin with POST /notes and GET /notes/{id}. That default has no public/index.html or greeting form. Do not treat it as the first linked Web Plugin in this two-Plugin tutorial.

1. Build the CLI from the matching source checkout

From the root of the current LioRael/lenso source checkout, with Rust and Cargo installed:

cargo build --locked -p lenso-cli --bin lenso
LENSO_CLI="$(pwd)/target/debug/lenso"
"$LENSO_CLI" app create --help

Confirm that app create --help succeeds. The installed lenso on your PATH may be an older public release; use the absolute LENSO_CLI path for every step here. The starter runs a Cargo check during creation. Cargo obtains the generated App's pinned packages from crates.io. For offline work, supply a reviewed mirror with those same versions; do not replace them with local path or Git overrides.

2. Create and run the same App

Use the same shell as above. A temporary parent keeps this preview outside the framework checkout; choose your own empty parent instead for a durable App.

APP_PARENT="$(mktemp -d)"
"$LENSO_CLI" app create "$APP_PARENT/hello-web" --web
cd "$APP_PARENT/hello-web"
"$LENSO_CLI" app dev

The first App-owned Web Plugin is app/local.starter/; it owns public/index.html and its own Cargo.toml. The App root is not a Cargo package in this mode. The generated Host supplies Web Ingress; you did not write a Host Catalog or Plan. Keep app dev running and open the Listening on http://... address printed by the Host. Do not assume a fixed port.

Enter Ada in the page's form and choose Create greeting. The page should show Hello, Ada! from the Plugin's POST /greetings endpoint. Inspect the browser console and network response if it does not. Seeing only the HTML page is not completion: the POST must succeed.

3. Add a second linked Web Plugin

Stop app dev, then run from hello-web/:

"$LENSO_CLI" plugin new example.second-http --web --repo-root ./app

This creates app/example.second-http/ with its own Cargo.lock. Its generated greeting route IDs and paths collide with the first Plugin. In the second Plugin, change greetings.create and POST /greetings to second.greetings.create and POST /second/greetings; change greetings.search and POST /greetings/search to second.greetings.search and POST /second/greetings/search. Update the generated tests to use those IDs and paths. Add app/example.second-http/src/routes/home.rs for a browser-visible second route:

#[get("second.home", "/second")]
async fn home(&self) -> Result<HandleResponse, Problem> {
    Ok(lenso_capability_http_endpoint::response::text(
        StatusCode::OK,
        "second Web Plugin",
    ))
}

The generated Plugin already imports the types used here. The Host rejects route collisions before Ready. See Local App development for the discovery and composition rules.

4. Build and inspect the result

From hello-web/, run:

"$LENSO_CLI" app discover --json
cargo test --locked --manifest-path app/example.second-http/Cargo.toml
"$LENSO_CLI" app build --out dist-review
"$LENSO_CLI" app check --root dist-review
"$LENSO_CLI" app show --root dist-review/intent --json
"$LENSO_CLI" app start --from dist-review --check

app build refuses to overwrite an existing output directory. app check takes the distribution root and verifies its Host bundle inventory; app show takes the distribution's intent/ Plugin Root to inspect the resolved result. start --check activates and shuts down. A successful App build does not create a signed catalog release or deploy the App. To check live HTTP, run "$LENSO_CLI" app start --from dist-review and visit / and /second at the address it prints.

Use a coding agent for these same steps

Give an agent the matching checkout and an empty local parent directory, then use this bounded request:

Create the local Web App using the manual commands in this page, with the
source-built lenso CLI from this checkout. Resolve the generated exact Cargo
pins from crates.io or a reviewed offline mirror. If a pin is unavailable,
stop and report the missing package and version without changing the generated
manifest or using a local path or Git override. Keep the App outside the
framework source tree: run
APP_PARENT="$(mktemp -d)"; run "$LENSO_CLI" app create "$APP_PARENT/hello-web" --web;
cd "$APP_PARENT/hello-web"; then run "$LENSO_CLI" app dev.
A bare app create instead makes a root Process notes Plugin and is not this
tutorial. In a real browser, submit Ada and show the Hello, Ada! result and
any console errors.
Stop dev, create example.second-http with plugin new --web --repo-root ./app,
give its routes distinct IDs and paths, add the GET /second route, and update
its tests. Run discover, the second Plugin's tests, build, check, show,
start --check, and live GETs for / and /second. Report the exact CLI revision,
commands, App path, output path, browser URL, and failures.

The agent may edit ordinary business code in app/local.starter/ and app/example.second-http/, but App selection and authority still come from the App's plugins/ root and Host. The Site cannot operate your local files or approve installation for you.

Add another Plugin only when it is real

Browse Plugins to inspect distribution, version, targets, and documentation. The historical lenso.web-ingress 0.4.5 candidate page is not a signed catalog release or an installation instruction. Even a signed linked Cargo listing is not an installed Plugin: your CLI must verify the exact snapshot, public trust, .crate, Host target, build, and resolved App. The local starter needs no catalog adoption to complete its greeting.

For the standalone Plugin workflow, keep using the existing Plugin quickstart. To understand how local App discovery and packaging work, continue with Local App development. To connect an ordinary React page to a typed public API, continue with the React/Vite candidate path.

Return to the Build an App path for configuration, inspection, and versioned Plugin documentation.

On this page