v1.2.0
loco-rs/locov1.2.0Sep 24, 2026by jondot
Upgrading?
AI Summary
Loco 1.2.0 introduces a coding agent skill, presigned storage URLs, row-level multi-tenancy, Tera 2 component support, and Postgres-only builds. The release also fixes a long list of defects in generated scaffolding and application behaviors, including a root 404 error and SPA issues.
Key Highlights
- Loco skill for coding agents to write idiomatic code.
- Presigned storage URLs for direct S3, Azure Blob, or GCS uploads/downloads.
- Row-level multi-tenancy support behind an opt-in feature.
- Tera 2 component rendering and Postgres-only builds.
- Fixes for generated app defects, including the root 404 error and SPA issues.
Breaking Changes
- `perform_later_with_priority` now returns an error when no queue provider is configured instead of logging and fabricating a job ID.
- `ExprTrait` is no longer re-exported from the prelude, requiring explicit imports for certain expression traits.
New Features
- Presigned storage URLs via `ctx.storage.presign_get` and `presign_put`.
- Row-level multi-tenancy with `TenantEntity`, `.in_tenant()`, and `set_tenant`.
- Tera 2 support including `TeraView::render_component`.
- Postgres-only builds via the `db-sqlite` feature.
- Batch job enqueueing with `perform_all_later`.
- Loco skill for coding agents in `.claude/skills/loco/`.
Full Release Notes
**[Read the announcement →](https://loco.rs/blog/loco-1-2-0/)** Ships a Loco skill so coding agents write idiomatic Loco without guessing, adds presigned storage URLs, row-level multi-tenancy, Tera components and Postgres-only builds, and fixes a long list of defects in the app `loco new` generates — including a server-side app that returned 404 at `/`. **Upgrading:** nothing to do for most apps. Two behaviour changes are listed below; neither needs an edit unless you were relying on the old behaviour. ### Breaking - **`perform_later_with_priority` now returns an error when no queue provider is configured.** It previously logged and handed back a fabricated job id, so an app with a misconfigured queue was told every enqueue had succeeded. It now returns `Error::QueueProviderMissing`. (#1821, @mccormickt) - **`ExprTrait` is no longer re-exported from the prelude.** It is `impl<T> ExprTrait for T where T: Into<Expr>`, and primitives are `Into<Expr>`, so it reached every value in every file that globs the prelude: `n.max(1)` stopped compiling, and `n.eq(&3)` kept compiling while returning an `Expr` instead of a `bool`. Import it explicitly if you need it. ### Added - **Presigned storage URLs.** `ctx.storage.presign_get(path, ttl)` and `presign_put(path, ttl, PresignPutOptions)` hand a client a time-limited URL that talks to S3, Azure Blob or GCS directly, so large uploads and downloads skip the app. Drivers that cannot presign return an error; on `ReplicatedStrategy` presigning is primary-only. (#1827, @robertazzopardi) - **Row-level multi-tenancy**, behind the opt-in `multi-tenancy` feature. `TenantEntity` names an entity's tenant column, `.in_tenant(id)` scopes selects and bulk updates/deletes, and `set_tenant` assigns the key on new records and refuses to overwrite a different one. Scoping is explicit at the call site; a query without `.in_tenant` is unscoped. (#1824, @shuvroroy) - **`TeraView::render_component`** renders a single Tera 2 component by name, autoescaped like `render`. Plus a guide to converting Tera 1 templates to Tera 2 with an AI assistant, covering the places it gets subtly wrong. (#1822, @schungx) - **Postgres-only builds.** SQLite support is now its own `db-sqlite` feature, on by default. Apps that set `default-features = false` and leave it out skip `libsqlite3-sys` and its C toolchain entirely. (#1828, @robertazzopardi) - **A Loco skill for coding agents.** `skills/loco/` carries the framework's doctrine, a generated API index covering `loco-rs` and Sea-ORM, and ten task recipes. `loco new` writes it into every generated app under `.claude/skills/loco/`, matched to that app's crate version, and it is served at <https://loco.rs/skills/loco/>. `cargo xtask agent-skill --check` keeps the derived outputs from drifting out of step with the source. - **Batch job enqueueing.** `perform_all_later(&ctx, args_list)` and `perform_all_later_with_priority` enqueue many jobs in a single round trip, atomically, on all three backends. Fanning out with a loop of `perform_later` cost N round trips and could leave the queue half-populated when one of them failed. (#1821, @mccormickt) - **`cargo loco task user:delete`** in generated apps, beside `user:create`. Takes a pid, prints the user it matched, and confirms before deleting; `force:true` skips the prompt for scripted use. (#1708, @floscodes) ### Fixed - **A Redis worker could stop draining its queue while the process stayed up.** `redis` 1.x changed its default connect timeout from none to one second and its response timeout to 500ms, so on a small instance booting against a managed Redis the worker failed to connect and exited; a dropped connection mid-run also ended it. Workers now use explicit timeouts, retry with backoff, and reconnect on a dead socket. (#1831, @mikosco4real) - **A server-side app returned 404 at `/`.** `assets/views/home/hello.html` shipped with a test that rendered it and no route that served it, so the first URL anyone opened was a 404. Generated apps now ship `controllers/page.rs` and a request test that exercises the route rather than the template. - **Nine defects in the generated SPA.** No sign-up page — the SaaS starter ships JWT auth as its headline feature and told users to `curl POST /api/auth/register`. A Vite dev proxy hardcoded to port 5150 while the backend reads `PORT` from config, so overriding the port sent every `/api` call somewhere else. A dead-end `Home.tsx`. Booleans rendering as blank cells in both list and detail views. List and detail disagreeing on which column holds the title, producing links with no text. And `vite build` never typechecking, because esbuild strips types without checking them — it is now `tsc -b && vite build`. - **Scaffolded controller actions were all routed as `GET`.** `create` was reachable by `GET`, `delete` by `GET`. Actions are now wired to the verb their name implies, and the generated tests call them that way. - **TypeScript bindings were written for apps with no frontend.** `#[ts(export)]` is a side effect of `cargo test`, not an annotation, so running the suite in an `--assets none` app conjured a `frontend/src/bindings/` tree out of nothing. - **The generated model test asserted nothing.** It booted the app, seeded, and returned. It now queries the entity, which fails when the migration and the entity disagree — a renamed column, a type that does not round-trip, a migration that never ran. - **The generated Dockerfile pinned a Rust older than the crate's MSRV**, so `cargo loco generate deployment docker && docker build` failed on a freshly generated app. - **The prelude withheld Sea-ORM query traits every app needs.** It carried `QueryFilter` but not `QueryOrder`, so `.filter()` compiled and `.order_by_desc()` on the next line did not — reported as a missing method rather than a missing trait. Loco had been working around this in its own generated scaffold. - **The prelude's `Pager` re-export was not gated behind `with-db`**, so every DB-less app failed to compile `loco-rs` itself. ### Docs - "The Tour" rewritten against what the generator actually emits today. (#1829, @Data5tream) - Indonesian README. (#1823) - A copy-paste agent prompt for upgrading 1.0 → 1.1. - The Japanese README could not reach the English or Spanish translations. ### Internal - CI pinned its toolchain instead of floating on `stable`, which meant new pedantic and nursery lints turned master red on a calendar rather than on a change. `style` also gated seven other jobs, so a lint error in an unrelated file reported build, test, msrv and examples as SKIPPED — two contributors spent two weeks looking at a red X that was ours. A weekly `lint:future` job now runs the same lints on `stable` and `beta` so the next set arrives as a scheduled failure instead of on someone's PR.
Related Repositories
A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io
An open-source remote desktop application designed for self-hosting, as an alternative to TeamViewer.
Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
π RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.
Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one