Development

Changelog

Release changes covered by the latest GoLazy guides.

By Guillermo Alvarez - Published - Updated

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/pg starts the PostgreSQL implementation module for framework backends. The first slice adds shared pgx pool helpers, pgmigrate for golazy.dev/lazymigrate, and pgjobs for durable lazyjobs. PostgreSQL migrations use -- +lazy Up and -- +lazy Down sections. Read PostgreSQL.
  • lazyfiles and lazymedia keep their append-only JSONL repositories in golazy.dev/lazyfiles/jsonl and golazy.dev/lazymedia/jsonl. The parent packages expose Repository interfaces for concrete backends, while the JSONL packages provide JSONLRepository implementations. Read Mailers And Storage.
  • lazyapp.Config.Dependencies now receives a framework-owned *lazydeps.Scope. Applications initialize services through lazydeps.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.SEO now receives the dependency-initialized app context and is normally wired as SEO: SEO with the function defined in init/seo.go. Read SEO And Sitemaps.
  • Sitemap generation is now opt-in. GoLazy does not serve an empty /sitemap.xml by default, and robots.txt only advertises a generated sitemap after lazyapp.Config.Sitemap is configured.
  • golazy.dev/lazyconfig fills application config structs from environment variables with Getenv[T] and MustGetenv[T], default field naming, var, default, required and require tags, trimmed string/numeric/bool values, pointer scalar fields, []string splitting, case-insensitive bool parsing, slice entry loading, and optional Validate() error support.
  • 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/progress provides named task progress, captured output, warnings, mise command helpers, and UI takeovers for interactive terminal steps.
  • lazyapp.ListenAndServe now mounts the standard pprof handlers automatically on the control plane when CONTROL_PLANE_ADDR runs on a different listener from the application. Same-listener and manually served control planes still require lazycontrolplane.Config{Pprof: true}.
  • golazy.dev/lazyerrors provides application-owned errors that format like fmt.Errorf, prefix messages with the caller, preserve single and multiple %w wrapping, and expose recorded []lazyerrors.Frame backtraces.
  • golazy.dev/lazytelemetry provides OpenTelemetry-compatible environment config, request-id middleware, context-aware slog logging, OpenTelemetry-backed spans, log-to-span events, OpenTelemetry meter measurements, and in-memory request metrics. lazyapp.New installs telemetry automatically when meaningful OTEL_* environment variables are present, mounts Prometheus text metrics on the control plane when OTEL_METRICS_EXPORTER=prometheus and CONTROL_PLANE_ADDR is set, and includes lazycache stats in that scrape output. Production builds do not expose control-plane metrics on the public app listener when CONTROL_PLANE_ADDR is unset. OTEL_SDK_DISABLED=true disables telemetry. Lazydev builds can also record per-request Go runtime traces, span JSON, and request-local log JSONL under .tmp/traces when 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.Irregular lets 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 PodMonitor resources for the GoLazy control-plane /metrics endpoint.
  • lazyapp now layers application views over framework default views from lazycontroller, so controller errors render a built-in mobile friendly app/error page unless the app provides app/views/app/error.html.tpl. Raw error details plus lazyerrors and 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, and lazydev can open a clicked frame in $EDITOR, using VS Code's -g file:line form or a discovered terminal for terminal editors. New apps can rely on that framework view and add app/views/app/error.html.tpl only when they want a custom error page.
  • lazycontroller.Base now provides SetLater and SetWhenNeeded for request-local deferred view data. They store a Valuer under 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_to with path_for, attr, data, and unless_current to render route links without handwritten anchor tags. Read Template Data And Helpers.
  • golazy.dev/lazycache provides the cache contract, typed Get / Set helpers, standardized stats, and On / Off switching. lazyapp installs a default in-memory backend, exposes App.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.Layout is the named-layout selection API. The previous SetLayout alias is removed in v0.1.17. CacheKey and CacheKeyF now return true when they wrote an existing cached response, so controller actions should return nil immediately on a cache hit. lazy upgrade --target v0.1.17 rewrites common call shapes automatically. Read Caching and Views And Layouts.
  • golazy.dev/lazyjobs provides a background job runner with typed JSON job payloads, an in-memory backend, retries, app-context injection through lazyapp.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-source connection 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. lazy also 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 lazydeps graph at GET /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 /readyz not ready, showing active requests and connections, waiting for active requests to drain, and coloring services as each dependency is canceled.
  • The lazy development proxy now serves Chromium Automatic Workspace Folders metadata at /.well-known/appspecific/com.chrome.devtools.json, pointing Chrome DevTools at the app's app/js source 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.js owns 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 .spans and .log.json request 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 .spans sidecar 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 check attempts 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-source URL 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 All as 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/lazymigrate provides 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 new now renames the generated command directory from cmd/app to cmd/<app-name> and rewrites template docs and build commands to match.
  • lazy new now trusts the generated app's mise.toml, runs mise install, validates with the current go on PATH, then initializes a fresh Git repository and commits the generated checkout with a command-local GoLazy identity.
  • lazy new checks https://golazy.dev/lazy.version before 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, and usage helper versions instead of using latest, so fresh mise install runs do not need a release-list lookup to decide the version.
  • LAZY_MULTIVERSION=off disables app-version CLI handoff for local testing, replacing the previous global --skip-version-check flag.
  • Go subprocesses in lazy new, lazy, lazy routes, lazy upgrade, and the app build step of lazy native build use the current go on PATH. lazy js and lazy tailwind choose app package managers from active installed mise tools in pnpm, yarn, bun, node order. Mise-selected managers run through mise exec; apps without a usable mise package-manager tool fall back to direct npm / npx.
  • lazy js keeps app-owned app/js files 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 js now names app-owned browser modules relative to the app/js root. Layouts import app.js, generated Stimulus wiring imports controllers such as controllers/hello_controller.js, and importmaps point those stable names at hashed lazyshaft assets.
  • The default lazy development command runs go mod tidy before building the app only when Go workspace mode is inactive. If GOWORK or go env GOWORK points at an active workspace, lazy skips the tidy step.
  • The default lazy development 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 lazy development 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 EventSource connections. 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 lazy development 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/extension on 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 for app/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, and bottom directions plus pixel or percentage size bounds.
  • The default lazy development command now assigns X-Request-ID and traceparent before proxying app requests and starts the child app with OTEL trace and log exporters enabled for lazydev request artifacts.
  • lazy now passes local view and public roots to lazydev builds with build-time variables. Development assets are served from disk by logical path without permanent hashes or cache headers.
  • lazy dump <dataset> and lazy load <dataset> now coordinate local service data snapshots under datasets/<dataset>/<service>.dump. Services are resolved from lazy.toml or discovered :start mise tasks, and dump/load behavior stays app-owned through service tasks. Read Services and Datasets.
  • When local services are configured or discovered, lazy starts them as managed subprocesses in parallel, records stdout and stderr, waits on available check tasks, runs create and migrate when 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 lazy development now reload the running app's view cache through POST /views on 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 upgrade includes the v0.1.14 to v0.1.15 dependency initializer and SEO initializer migrations, and recognizes v0.1.16 as 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 upgrade applies go.mod dependency manifests with go get instead of rewriting module files directly, and it updates mise.toml tools through a tool manifest that comments obsolete entries rather than deleting them.
  • lazy upgrade file 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 --version now reports v0.1.16, so lazy new selects 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 when GOBIN is not set, tries the official shell-specific mise installer for bash, zsh, or fish, falls back to the plain bootstrap, and points new apps at lazy. Its same-shell recovery path now keeps lazy on the normal PATH so direct Go subprocesses still find go.
  • The homepage and package pages emit richer social-card metadata using the new SEO helpers.
  • The latest guides document the in-development v0.1.16 changes while v0.1.15 stays frozen as the previous release snapshot.

Read the Upgrade Guide before moving an existing application forward.