Skip to content

Go

A complete, copy-paste walkthrough: start a new Go HTTP service (standard library, no dependencies), snapshot its rendered page with Dungbeetle, change a handler, and read the semantic diff. It uses the default web capture with the zero-dependency fetch driver — no browser install required. A CLI variant is at the end.

Prerequisites

  • Go 1.21+ (go version).
  • Node.js 22 or newer — Dungbeetle's runtime (node --version).

1. Create a new Go service

Make a project, initialize a module, and write a minimal net/http server:

sh
mkdir go-service && cd go-service
go mod init example.com/go-service

Create main.go:

go
package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "<html><body><h1>Hello from Go</h1></body></html>")
	})
	http.ListenAndServe(":8080", nil)
}

Run it to confirm it serves at http://127.0.0.1:8080:

sh
go run .

The Go service's page in a browser at http://127.0.0.1:8080.

2. Install Dungbeetle

sh
npm install --save-dev dungbeetle
npx dungbeetle --version

This adds a package.json to the project; commit it alongside your Go code.

3. Scaffold a config

Generate a starter config, then replace it with the one below. It starts the service, waits until it responds, and snapshots the page — then shuts the service down:

sh
npx dungbeetle init
json
{
  "version": 1,
  "project": { "name": "go-service" },
  "baselinesDir": "dungbeetle.snapshots",
  "artifactsDir": ".dungbeetle/artifacts",
  "lifecycle": {
    "start": ["go run ."],
    "wait": { "url": "http://127.0.0.1:8080", "timeoutMs": 30000 },
    "capture": [
      { "kind": "web", "name": "index", "url": "http://127.0.0.1:8080" }
    ]
  }
}

The web target uses the default fetch driver (no Playwright, no browser). See Web snapshots and the full configuration reference.

4. Validate the setup

sh
npx dungbeetle doctor

5. Capture the first baseline

sh
npx dungbeetle update

Dungbeetle boots the service, waits for http://127.0.0.1:8080, captures a structured DOM snapshot, writes it under dungbeetle.snapshots/, and stops the service. Commit the baseline:

sh
git add dungbeetle.snapshots
git commit -m "Add Dungbeetle baseline for index route"

6. Make a change and compare

Edit the heading in main.go:

go
		fmt.Fprint(w, "<html><body><h1>Hello from Example Service</h1></body></html>")

Now compare current output against the baseline:

sh
npx dungbeetle test

test boots the service again, re-captures, and exits non-zero because the DOM changed. The diff is semantic — a node-level text-changed, not a pixel blob.

7. Read the report

sh
npx dungbeetle ci --json report.json --html report.html
open report.html   # macOS; use xdg-open on Linux

Screencast: doctor → the edited main.go fails test with a semantic diff → update accepts it → test passes.

Flow video — the terminal session replayed, then the served page with its change, then the failing run's HTML report.

8. Accept the new baseline

sh
npx dungbeetle update
git add dungbeetle.snapshots && git commit -m "Update index baseline"

Snapshot a CLI instead

For a command-line binary, capture stdout/stderr with a terminal target instead of a web one — no server needed. Build first, then snapshot:

json
{
  "version": 1,
  "project": { "name": "go-cli" },
  "lifecycle": {
    "setup": ["go build -o yourtool ."],
    "capture": [
      { "kind": "terminal", "name": "help", "command": "./yourtool --help" }
    ]
  }
}

dungbeetle update / test then snapshot and diff the command's output, with ANSI normalized to stable structured segments.

9. Review in the cloud

Push a run to a Dungbeetle server and the review UI shows the whole story in one place: the DOM's semantic diff, the cart-api JSON diff with its numeric changes, and before/after screenshots from the Playwright driver.

Screencast: sign in → open the failing run → semantic diffs, screenshot comparison with onion skin → approve and promote the new baselines.

Next steps

  • Add a web target per route, or mix web and terminal targets in one config.
  • Frameworks like Gin or Echo work the same way — point start at your run command and set wait.url to match the listen address.
  • Need browser-rendered DOM or screenshots? Use the Playwright driver. Push runs to the cloud server to review diffs in a browser.

Source-available: CLI under FSL-1.1-ALv2, cloud server under BUSL-1.1. See Licensing.