Development

Upgrade Guide

Upgrade an existing GoLazy application to the latest GoLazy release.

By Guillermo Alvarez - Published - Updated

Upgrade from v0.1.16

GoLazy v0.1.17 changes two controller APIs:

  • c.SetLayout("name") becomes c.Layout("name").
  • c.CacheKey(...) and c.CacheKeyF(...) now return true when an existing cached body was written. Return nil immediately on that hit, then continue setting controller data and rendering on a miss. Render cache keys now also include the app build version, and active render variants when present, so existing in-memory render cache entries naturally miss after a new build.

Run the automated migration:

lazy upgrade --target v0.1.17

The migration updates the golazy.dev module requirement, rewrites common SetLayout, CacheKey, and CacheKeyF controller call shapes, and keeps the normal upgrade checks in place.

Upgrade from v0.1.15

GoLazy v0.1.16 does not require source rewrites for applications that already run on v0.1.15. The release adds framework cache support, deferred template values, route-link helpers, richer telemetry, and the DevTools-style lazydev panel. Use lazy upgrade to update the golazy.dev module requirement and run the normal follow-up checks.

After updating the CLI, the default lazy development proxy may show a local HTTPS setup page on the plain HTTP address. Install the GoLazy local certificate authority once per machine or browser trust store to use the development panel and proxied app over HTTPS on the same port. This does not require application source changes.

Install or update the matching CLI:

curl -fsSL https://golazy.dev/install.sh | sh
lazy --version

Run the application migration:

lazy upgrade --target v0.1.16

lazy upgrade applies the framework module update with go get from the release's go.mod manifest, then runs the standard follow-up checks. It does not edit application source for the v0.1.15 -> v0.1.16 step.

Apps that adopted the early JSONL repositories for lazyfiles or lazymedia should update their imports and constructors:

filesRepo, err := filesjsonl.New("storage/files.log.jsonl")
mediaRepo, err := mediajsonl.New("storage/variants.log.jsonl")

Use golazy.dev/lazyfiles/jsonl and golazy.dev/lazymedia/jsonl for those aliases. The parent packages continue to expose the Repository interfaces used by lazyfiles.Files and lazymedia.Media.

Asset commands may change which Node package manager they use after the CLI upgrade. lazy js and lazy tailwind now prefer active installed mise tools in pnpm, yarn, bun, node order, with node mapped to npm. If mise cannot provide one of those tools, the commands fall back to direct npm / npx. No application source migration is required for this behavior change.

After updating to a CLI with the current lazy js behavior, app-owned files under app/js regenerate as readable, unbundled, content-hashed assets. Manifest library entrypoints remain bundled. App-owned importmap specifiers are now relative to app/js: layouts import app.js, and generated Stimulus code imports controllers such as controllers/hello_controller.js. Run lazy upgrade to rewrite old /js/... imports; the v0.1.17 migration runs lazy js automatically when js.toml is present. Commit the refreshed importmap and lazyshaft files when the generated output changes.

lazy dump, lazy load, and the managed service preparation flow are additive. No source migration is required. Apps can opt in by adding service lifecycle tasks under .mise/tasks/<service>/ and, when explicit ordering is needed, listing service names in lazy.toml.

If you are upgrading from v0.1.14 or earlier, first run the earlier automated migrations or read the previous versioned upgrade guides. The v0.1.14 -> v0.1.15 step still migrates dependency initializers and SEO defaults before the v0.1.16 module update runs.

Review New Features

Caching

lazyapp.App now owns a default cache and exposes it through golazy.dev/lazycache. Controller views, partials, and Turbo frame bodies can use the cache helpers. Render cache keys include the app build version and active render variants when present. Lazydev exposes cache state, keys, entry content, and On/Off actions. Read Caching.

Deferred Template Values

Controllers can use SetLater and SetWhenNeeded when a template value is expensive or only needed in some render paths. Templates resolve the value with .Value. Read Template Data And Helpers.

Templates can use link_to, path_for, attr, data, and unless_current to render escaped links to named routes without handwritten anchor tags. Read Template Data And Helpers.

Telemetry

GoLazy can enable OpenTelemetry-compatible tracing, logging, request IDs, and in-memory metrics from meaningful OTEL_* environment variables. Set OTEL_SDK_DISABLED=true to disable telemetry explicitly. Prometheus metrics are served from the control plane when OTEL_METRICS_EXPORTER=prometheus and CONTROL_PLANE_ADDR are configured. Read Telemetry.

Background Jobs

Applications can opt into golazy.dev/lazyjobs through lazyapp.Config.Jobs. Existing apps do not need source changes unless they want background jobs. Read Background Jobs.

lazydev Panel

The lazy development loop now embeds a DevTools-style panel at /_golazy/ with App, Requests, Services, Routes, Jobs, BuildInfo, Assets, and Cache tabs. It also forwards request IDs and trace context to the child app so panel artifacts line up with framework telemetry. The Requests tab can list captured request paths, filter by path or category, and open lazy-loaded Headers, Tracing, and Logs details when detailed request monitoring is enabled. The Routes tab reads the app's development control plane, so no application source change is needed to see registered routes there; static GET routes link to the running app. The BuildInfo tab shows the running app's Go version, command path, main module, dependencies, replacements, recorded build settings, and the last Go build trace summary; no application source migration is required. The Dependencies tab shows the running app's lazydeps service graph, progressively enhanced into SVG from server-rendered table rows. It can simulate lazydev shutdown by sending 10 requests per second to the app root for a configured delay, marking /readyz not ready, showing active requests and connections, and coloring services as dependency cancellation progresses; no application source migration is required. The App tab owns app status, changed-file groups, and rebuild, restart, and open-app controls. The Services tab can restart, stop, or start managed local services when service lifecycle tasks are present, groups output by service tree and script name, parses JSON log lines into message and attribute columns, caps log output at 100 rows, and shows run numbers for repeated task attempts such as check; no application source migration is required. The Assets tab lists the app asset manifest and public paths, and the Cache tab shows cache size, usage, searchable keys, selected entry content, and cache controls. Detailed request monitoring also adds per-region self time and allocation samples to the Requests tab without requiring application source changes. Panel tab streams hydrate their lists when they connect and then update only from relevant backend events. The status bar keeps its status stream inside the permanent Turbo frame, so tab switches keep one long-lived status connection; no application source migration is required for that behavior. The proxy also serves Chrome DevTools Automatic Workspace Folders metadata for the app's app/js folder; no application route or source migration is required. The injected host script also exposes window.disableDevPanel() for the Chrome DevTools extension; no application source migration is required. The proxy now injects hidden panel host markup that is controlled by devpanel_controller.js; no application template migration is required. Read lazydev and Lazy.

The same public port accepts plain HTTP and HTTPS. Plain HTTP serves the local certificate authority setup page until the browser trusts the GoLazy CA; HTTPS serves the panel and proxied app traffic, with HTTP/2 available for the panel's long-lived streams.