Development
Upgrade Guide
Upgrade an existing GoLazy application to the latest GoLazy release.
Upgrade from v0.1.16
GoLazy v0.1.17 changes two controller APIs:
c.SetLayout("name")becomesc.Layout("name").c.CacheKey(...)andc.CacheKeyF(...)now returntruewhen an existing cached body was written. Returnnilimmediately 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.
Route Link 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.