Development
Changelog
Release changes covered by the latest GoLazy guides.
Latest release changes
GoLazy v0.1.16 adds cache primitives, deferred template values, route-link
template helpers, OpenTelemetry-backed request telemetry, and a richer lazydev
development panel. Existing v0.1.15 applications do not need source rewrites;
run lazy upgrade --target v0.1.16 to update the golazy.dev module
requirement and follow-up checks.
Framework
golazy.dev/pgstarts the PostgreSQL implementation module for framework backends. The first slice adds shared pgx pool helpers,pgmigrateforgolazy.dev/lazymigrate, andpgjobsfor durablelazyjobs. PostgreSQL migrations use-- +lazy Upand-- +lazy Downsections. Read PostgreSQL.lazyfilesandlazymediakeep their append-only JSONL repositories ingolazy.dev/lazyfiles/jsonlandgolazy.dev/lazymedia/jsonl. The parent packages exposeRepositoryinterfaces for concrete backends, while the JSONL packages provideJSONLRepositoryimplementations. Read Mailers And Storage.lazyapp.Config.Dependenciesnow receives a framework-owned*lazydeps.Scope. Applications initialize services throughlazydeps.Service, update the app context through the scope, and let GoLazy record the dependency graph for later lifecycle work. Read Application Startup and Dependencies And Services.lazyapp.Config.SEOnow receives the dependency-initialized app context and is normally wired asSEO: SEOwith the function defined ininit/seo.go. Read SEO And Sitemaps.- Sitemap generation is now opt-in. GoLazy does not serve an empty
/sitemap.xmlby default, androbots.txtonly advertises a generated sitemap afterlazyapp.Config.Sitemapis configured. golazy.dev/lazyconfigfills application config structs from environment variables withGetenv[T]andMustGetenv[T], default field naming,var,default,requiredandrequiretags, trimmed string/numeric/bool values, pointer scalar fields,[]stringsplitting, case-insensitive bool parsing, slice entry loading, and optionalValidate() errorsupport.- SEO helpers support image alt text, Open Graph image dimensions, secure
social image URLs,
article:published_time, and complete-title preservation. Read SEO And Sitemaps. golazy.dev/lazytui/progressprovides named task progress, captured output, warnings, mise command helpers, and UI takeovers for interactive terminal steps.lazyapp.ListenAndServenow mounts the standard pprof handlers automatically on the control plane whenCONTROL_PLANE_ADDRruns on a different listener from the application. Same-listener and manually served control planes still requirelazycontrolplane.Config{Pprof: true}.golazy.dev/lazyerrorsprovides application-owned errors that format likefmt.Errorf, prefix messages with the caller, preserve single and multiple%wwrapping, and expose recorded[]lazyerrors.Framebacktraces.golazy.dev/lazytelemetryprovides OpenTelemetry-compatible environment config, request-id middleware, context-awaresloglogging, OpenTelemetry-backed spans, log-to-span events, OpenTelemetry meter measurements, and in-memory request metrics.lazyapp.Newinstalls telemetry automatically when meaningfulOTEL_*environment variables are present, mounts Prometheus text metrics on the control plane whenOTEL_METRICS_EXPORTER=prometheusandCONTROL_PLANE_ADDRis set, and includeslazycachestats in that scrape output. Production builds do not expose control-plane metrics on the public app listener whenCONTROL_PLANE_ADDRis unset.OTEL_SDK_DISABLED=truedisables telemetry. Lazydev builds can also record per-request Go runtime traces, span JSON, and request-local log JSONL under.tmp/traceswhen detailed request monitoring is enabled from the development panel. Framework request spans now include child regions for middleware, routing, dispatch, controller setup, action calls, view rendering, layouts, and partials. Request ids are attached to request spans, child regions, and log span-events. Read Telemetry.golazy.dev/lazysupport/inflection.Irregularlets applications register domain-specific singular/plural pairs before resource routes derive conventional names. Read REST Resources.- The latest telemetry guide now documents the Kubernetes production shape:
ingress-nginx OpenTelemetry is enabled per Ingress but collector and sampler
settings live on the nginx controller ConfigMap; Prometheus Operator scraping
should use
PodMonitorresources for the GoLazy control-plane/metricsendpoint. lazyappnow layers application views over framework default views fromlazycontroller, so controller errors render a built-in mobile friendlyapp/errorpage unless the app providesapp/views/app/error.html.tpl. Raw error details pluslazyerrorsand panic backtraces are exposed to that view only in development/detail mode. The built-in view shortens frame paths relative to the workspace, current directory, module cache, or module path where possible, andlazydevcan open a clicked frame in$EDITOR, using VS Code's-g file:lineform or a discovered terminal for terminal editors. New apps can rely on that framework view and addapp/views/app/error.html.tplonly when they want a custom error page.lazycontroller.Basenow providesSetLaterandSetWhenNeededfor request-local deferred view data. They store aValuerunder the template key and let templates call{{.name.Value}}while the controller can still use the returned value directly. Read Template Data And Helpers.- Templates can use
link_towithpath_for,attr,data, andunless_currentto render route links without handwritten anchor tags. Read Template Data And Helpers. golazy.dev/lazycacheprovides the cache contract, typedGet/Sethelpers, standardized stats, andOn/Offswitching.lazyappinstalls a default in-memory backend, exposesApp.Cache, and registers controller, partial, and Turbo frame body caching helpers. The development panel exposes cache stats, keys, searchable entry metadata, selected entry content, and On/Off actions through the lazydev control plane. Controller and template render cache keys include the app build version, and active render variants when present, to avoid stale bodies across deploys and variant-specific renders. Read Caching.lazycontroller.Base.Layoutis the named-layout selection API. The previousSetLayoutalias is removed inv0.1.17.CacheKeyandCacheKeyFnow returntruewhen they wrote an existing cached response, so controller actions should returnnilimmediately on a cache hit.lazy upgrade --target v0.1.17rewrites common call shapes automatically. Read Caching and Views And Layouts.golazy.dev/lazyjobsprovides a background job runner with typed JSON job payloads, an in-memory backend, retries, app-context injection throughlazyapp.Config.Jobs, and read-only job state on the control plane. The development panel now includes a Jobs tab. Read Background Jobs.- Separate control-plane listeners now serve a compact
GET /index that lists the registered control-plane endpoints. Same-listener control planes keep application/routes untouched. Read Control Plane. - The development panel now visits one resource-backed page per top-level tab and keeps the bottom status bar mounted as a permanent Turbo frame while you move between tabs. Read Lazydev Mode.
- Development panel tabs now hydrate list content through their
turbo-stream-sourceconnection and then send targeted row or count updates only when a relevant backend event exists, avoiding whole-tab refreshes from unrelated build events. - The Routes tab now reads the app lazydev control plane and renders a filterable route table with method, path, route name, controller target, route params, and namespace metadata. Route searches use debounced backend Turbo Frame requests that cancel older in-flight searches.
- Lazydev now exposes the running app's Go module build information at
GET /buildinfo, and the development panel's BuildInfo tab shows the app Go version, command path, main module, dependencies, replacements, and recorded build settings.lazyalso captures the Go command's build trace for each lazydev build and summarizes fetch, load, cache, build, and link timing plus the top five slowest packages in a two-sided BuildInfo view with runtime details, settings, and dependencies behind right-side tabs. - Lazydev now exposes the running app's
lazydepsgraph atGET /dependencies, and the development panel's Dependencies tab shows service rows plus directed dependency edges, progressively enhanced into an SVG graph by Stimulus. The tab can also simulate shutdown by sending 10 requests per second to the app root for a configured delay, then marking/readyznot ready, showing active requests and connections, waiting for active requests to drain, and coloring services as each dependency is canceled. - The
lazydevelopment proxy now serves Chromium Automatic Workspace Folders metadata at/.well-known/appspecific/com.chrome.devtools.json, pointing Chrome DevTools at the app'sapp/jssource folder. - The injected development-panel host script now exposes
window.disableDevPanel()so the Chrome DevTools extension can hide the in-page panel and launcher after the inspected page has loaded. - The development proxy now injects hidden panel host markup into proxied app
HTML, while
devpanel_controller.jsowns the in-page panel, spacer, launcher, resize, and extension state. - The in-page development panel launcher now uses the padded, yellow-backed GoLazy square logo in a rounded-square button, opens the panel on click, and stays hidden while the Chrome extension is active or the in-page panel is visible.
- The Requests tab now reads captured
.spansand.log.jsonrequest sidecars, lists captured request paths, filters by request path and request category on the app control plane, and opens lazy-loaded Headers, Tracing, and Logs detail tabs. The Tracing detail shows controller and view regions by default, can include framework regions, displays correlated logs, and renders a chronological flamegraph for the selected region. - The Requests Tracing detail now has a request status strip, an Include golazy toggle, a backend-sorted region metrics table, and a flamegraph scaled by the selected time, allocation, or memory metric. Flamegraph bars now use square classical flamegraph colors, keep span names inside the bars, and expose full timing and allocation details in tooltips. The flamegraph pane grows to the graph's full height after the region table reaches its compact minimum. Allocation and memory flamegraphs fall back to the request timeline when a trace has regions but no positive sampled metric values.
- Lazydev request sidecars and the Requests tab now show per-region total and self duration plus sampled allocation bytes, malloc counts, and free counts.
- Request trace rendering now stops parent-depth walks when captured span data
contains cyclic parent links, so a damaged
.spanssidecar cannot freeze the browser. - The development panel now uses one top tab bar, places the close button on the right, shows the app and services as status chips, opens the App tab from the app status chip, and moves app lifecycle state, changed-file groups, rebuild, restart, and open-app controls into that App tab.
- The Services tab now renders a service tree with a synthetic App service,
managed services, lifecycle scripts, and all discovered mise tasks. Service
logs are capped at 100 rows, batched while streaming, parse JSON log lines
into message and attributes columns, and show run numbers so repeated
checkattempts and restarted service runs are visible. - Managed service rows can now restart, stop, or start a service from the Services tree.
- The Assets tab now lists lazy asset manifest entries and public paths, and
filters them with debounced backend Turbo Frame requests that cancel older
in-flight searches. Route searches use the same request pattern. The Requests
filter keeps its tab stream and debounces updates to that
turbo-stream-sourceURL instead. The Cache tab hydrates from its tab stream, observes lazydev cache hit/miss/set events, updates summary counters individually, appends newly observed keys, and shows per-key hit/set metadata when the backend exposes it. - The Console and App Logs tabs were removed; app logs are merged into the Services tab.
- The development panel status bar now keeps its live status stream inside the permanent Turbo frame, so tab switches keep one long-lived status connection.
- The development panel layout now uses Turbo morph refreshes with scroll preservation, so refreshes can patch the panel document without resetting the user's scroll position.
- The development panel now remembers the last top-level tab in session storage and restores it when the embedded panel loads at the default App tab. Static GET route clicks from the Routes tab ask the injected host client to visit the app path with Turbo when available.
- Embedded development panels can now be resized from their top edge, and the proxied page's bottom padding follows the selected panel height.
- Development panel data tables now remember resized column widths, and rightward header drags continue compressing later columns after the immediate right column reaches its minimum width. Tables also scale columns proportionally when panes resize, grouped or multi-row headers resize their covered leaf columns proportionally, and frame-targeted row clicks update selected-row styling immediately.
- The Requests toolbar now combines a DevTools-style path filter with request
handler chips, includes
Allas the default handler filter, and removes the previous All, Framework, Assets, Other category filter row. - Closed in-page development panels now show a small yellow GoLazy launcher when the Chrome extension is not installed. The extension action toggles the inspected page's in-page panel, and the in-page panel hides while the GoLazy DevTools panel is open.
- The status bar app chip now opens App, and selected service chips keep the same background as the rest of the status bar.
golazy.dev/lazymigrateprovides backend-agnostic migration loading, source/backend diffing, up/down/redo planning, schema dump/load hooks, and a fake backend for tests. Real database backends and CLI wiring are deferred.
CLI and generated apps
lazy newnow renames the generated command directory fromcmd/apptocmd/<app-name>and rewrites template docs and build commands to match.lazy newnow trusts the generated app'smise.toml, runsmise install, validates with the currentgoonPATH, then initializes a fresh Git repository and commits the generated checkout with a command-local GoLazy identity.lazy newcheckshttps://golazy.dev/lazy.versionbefore remote template generation, supports--skip-update-check, and accepts--version <version>for a specific sample app tag.- Generated apps pin their mise-managed
age,sops, andusagehelper versions instead of usinglatest, so freshmise installruns do not need a release-list lookup to decide the version. LAZY_MULTIVERSION=offdisables app-version CLI handoff for local testing, replacing the previous global--skip-version-checkflag.- Go subprocesses in
lazy new,lazy,lazy routes,lazy upgrade, and the app build step oflazy native builduse the currentgoonPATH.lazy jsandlazy tailwindchoose app package managers from active installed mise tools inpnpm,yarn,bun,nodeorder. Mise-selected managers run throughmise exec; apps without a usable mise package-manager tool fall back to directnpm/npx. lazy jskeeps app-ownedapp/jsfiles readable and unbundled while still writing content-hashed lazyshaft assets and importmap entries. Manifest library entrypoints remain bundled. Read lazy js And js.toml.lazy jsnow names app-owned browser modules relative to theapp/jsroot. Layouts importapp.js, generated Stimulus wiring imports controllers such ascontrollers/hello_controller.js, and importmaps point those stable names at hashed lazyshaft assets.- The default
lazydevelopment command runsgo mod tidybefore building the app only when Go workspace mode is inactive. IfGOWORKorgo env GOWORKpoints at an active workspace,lazyskips the tidy step. - The default
lazydevelopment command now uses compact progress output for proxy startup, generated-asset work, Go builds, and application starts while leaving the running app's own output attached to the terminal. - The default
lazydevelopment command now serves a GoLazy development panel at/_golazy/, keeps it available across build and runtime failures, and starts the target app's development control plane on a separate internal address for route inspection, view-cache reloads, and cache inspection. - The development client now keeps one reload stream and one panel event stream
alive across Turbo visits instead of opening duplicate
EventSourceconnections. The panel event endpoint also uses the framework SSE stream helper so normal response wrappers do not turn the stream into a false 500. - The
lazydevelopment proxy now accepts plain HTTP and HTTPS on the same public port. HTTP serves a local HTTPS setup page with OS-specific instructions and a GoLazy certificate authority download; after the browser trusts that CA, the page redirects to HTTPS and the development panel can use HTTP/2 for app requests and panel streams. - The development panel now uses a DevTools-style tabbed shell, carries app
lifecycle, services, requests, assets, jobs, routes, and cache controls into
that shell, and embeds itself as a fixed bottom iframe on proxied app pages
instead of only showing a floating activator button. The unpacked Chrome
DevTools extension now probes
/_golazy/extensionon the inspected site and embeds that site's/_golazy/panel when the lazy development proxy is present. It also retries during page reloads, keeps the embedded panel iframe mounted during same-origin app navigation, exposes Chrome's automatic workspace metadata forapp/js, and lets the extension icon select the GoLazy DevTools panel when DevTools is already open. - The embedded development panel can now be closed from the panel toolbar.
Panel split panes use Stimulus-owned resize handles with
left,right,top, andbottomdirections plus pixel or percentage size bounds. - The default
lazydevelopment command now assignsX-Request-IDandtraceparentbefore proxying app requests and starts the child app with OTEL trace and log exporters enabled for lazydev request artifacts. lazynow passes local view and public roots tolazydevbuilds with build-time variables. Development assets are served from disk by logical path without permanent hashes or cache headers.lazy dump <dataset>andlazy load <dataset>now coordinate local service data snapshots underdatasets/<dataset>/<service>.dump. Services are resolved fromlazy.tomlor discovered:startmise tasks, and dump/load behavior stays app-owned through service tasks. Read Services and Datasets.- When local services are configured or discovered,
lazystarts them as managed subprocesses in parallel, records stdout and stderr, waits on availablechecktasks, runscreateandmigratewhen present, and stops the app before stopping services on interrupt. Read Lazy. - The development panel now includes a Services tab with per-service stdout/stderr rows, lifecycle-script output, run numbers, and bottom status-bar indicators that open the selected service output. Each service row can restart, stop, or start that managed service.
- View-only changes in
lazydevelopment now reload the running app's view cache throughPOST /viewson the app's development control plane instead of rebuilding and restarting the app. Public-only changes reload the browser without rebuilding because development assets are read from disk. lazy upgradeincludes thev0.1.14tov0.1.15dependency initializer and SEO initializer migrations, and recognizesv0.1.16as the next module-only upgrade target. It also uses compact progress output while still letting conflict diffs and prompts take over the terminal deliberately. Read the Upgrade Guide.lazy upgradeappliesgo.moddependency manifests withgo getinstead of rewriting module files directly, and it updatesmise.tomltools through a tool manifest that comments obsolete entries rather than deleting them.lazy upgradefile manifests now hash sample-app additions, replacements, and removals. Unchanged template-owned files are updated or removed directly, new files are created directly, and customized files ask for a dated backup, deletion, keep, or abort choice depending on the operation.lazy --versionnow reportsv0.1.16, solazy newselects the matching sample application template once the coordinated release is published.
Website and guides
- Package documentation headings now link directly to the matching GitHub
source line when source metadata is available, while the hover/focus
ΒΆlink remains the in-page permalink. - Guide code blocks now load their Highlight.js language modules through the local lazyshaft importmap, covering Go, TOML, text, shell, SQL, and the other latest-guide fence languages without unresolved browser module specifiers.
- The public installer installs
golazy.dev/lazy, writes the binary to a predictable local bin directory whenGOBINis not set, tries the official shell-specificmiseinstaller forbash,zsh, orfish, falls back to the plain bootstrap, and points new apps atlazy. Its same-shell recovery path now keepslazyon the normalPATHso direct Go subprocesses still findgo. - The homepage and package pages emit richer social-card metadata using the new SEO helpers.
- The latest guides document the in-development
v0.1.16changes whilev0.1.15stays frozen as the previous release snapshot.
Read the Upgrade Guide before moving an existing application forward.