{"app":"notes","env":"prod","sqlite":"3.53.2","welcome":"# Notes\n\nYou're on islas. This app is a small Rust backend compiled to WebAssembly: it runs on an islas hub at `notes.<domain>`, with its own SQLite database, key-value store, secrets and logs. The host keeps the connections, the storage and the time; the app is a set of handlers that answer requests and keep nothing between them.\n\nThis welcome is `src/controllers/welcome.md`, answered by `src/controllers/home.rs`. Replace both with your app.\n\n## Where things are\n\n| Path | What goes there |\n|---|---|\n| `app.toml` | the manifest: name, subdomain, routes, limits, required secrets, outbound hosts |\n| `config/routes.rs` | every route, drawn as in Rails |\n| `src/controllers/` | the shell of each request: parse, load, decide, save, answer |\n| `src/services/` | the rules, as pure functions, tested with plain `#[test]`s |\n| `src/models/` | structs and their SQL |\n| `migrations/` | the schema, one timestamped SQL file per change |\n| `tests/` | requests run against the app natively, with `islas::testing` |\n\n## What the app can use\n\n- **`db`**: its own SQLite database. `query_as::<Note>(sql, params)`, `execute`, `transaction(|| ..)`.\n- **`kv`**: a key-value store with expiry. `set_json_ttl`, `get_json`, `list(prefix)`.\n- **`secrets`**: values set in the hub, never in code. `secrets::get(\"API_TOKEN\")`.\n- **`fetch`**: outbound HTTP to the hosts `app.toml` allows.\n- **`web::session`, `web::csrf`, `crypto`**: sessions, CSRF tokens, sealed and signed values, on a key only this app has.\n- **`testing`**: the app's requests in a plain `cargo test`, the database in memory.\n\n## Guides\n\n**Add a resource.** `islas migrate new create_notes` and write the table; a model in `src/models/note.rs` (a struct, its SQL with `query_as`); the rules in `src/services/notes.rs` with their tests; a controller in `src/controllers/notes.rs` implementing `Resource`; a line in `config/routes.rs`: `r.resources::<Notes>(\"notes\", [Index, Create, Destroy])`; a test in `tests/`. `CLAUDE.md` has the code for each step.\n\n**Change the schema.** `islas migrate new <name>`, then write the SQL. `islas dev` applies it as you save; a deploy applies it on the server. A deployed migration is never edited: add another.\n\n**Add a secret.** `islas secrets set notes NAME` on the hub (the value on stdin); locally, in `.isla/secrets.json`. Read it with `secrets::get(\"NAME\")`; list it in `app.toml`'s `[secrets] required` if the app can't run without it.\n\n**Deploy.** `islas servers add <name> <url>` once, then `islas deploy --to <name>`; or push a release, and `.github/workflows/deploy.yml` deploys it (the README says what to set up).\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `islas dev` | builds and runs the app on http://localhost:3000 (and its page, when it has one), rebuilding as you save |\n| `cargo test` | the tests, natively |\n| `islas migrate new <name>` | a new migration |\n| `islas pack` | the zip a deploy takes |\n| `islas deploy --to <server>` | packs and deploys |\n| `islas logs notes --on <server>` | the app's log on the server |\n"}