Help us shape the future of Go! Take the 2026 Go Developer Survey

preview

package
v0.700.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package preview serves design artifacts over HTTP so every surface — the WebUI iframe, a system browser opened from the TUI, a Zed resource link — looks at the same running document instead of a file:// copy.

The package deliberately knows nothing about the design model: it is handed a directory and an entry document and hands back a URL. That keeps it free of any dependency on internal/design, so internal/design can import it to mint URLs while internal/api mounts the very same handler on the main listener.

Two deployments share one implementation:

  • mounted: internal/api registers Server.ServeHTTP under Prefix on the API listener, so the preview lives on the Pando origin and is reachable remotely through the existing external-access toggle.
  • loopback: processes without an API server (plain TUI, ACP, CLI) call Server.StartLoopback, which binds 127.0.0.1:0 and serves the same routes.

Every artifact is addressed through an unguessable per-artifact token in the path. The token is the capability: it is bound to the session that created it and dies with the grant, so a stale URL in someone's browser history stops resolving instead of exposing whatever now sits in that directory.

Index

Constants

View Source
const BridgePath = Prefix + "_bridge.js"

BridgePath serves the selection bridge. It sits outside the token space on purpose: it is a static asset with no artifact content in it, and keeping it token-free means one cached copy serves every artifact.

View Source
const DefaultTTL = 12 * time.Hour

DefaultTTL is how long a grant stays resolvable without being refreshed. Presenting an artifact refreshes it, so an artifact under active iteration never expires while the user is looking at it.

View Source
const Prefix = "/preview/"

Prefix is the single route prefix the server owns. Everything below it is artifact content; nothing above it is ever touched.

Variables

View Source
var ErrForbidden = errors.New("preview: refused")

ErrForbidden is returned by an access guard that refuses to serve. The API server uses it to keep previews off a network-facing listener that has no authentication in front of it.

Functions

This section is empty.

Types

type Grant

type Grant struct {
	Token      string `json:"token"`
	ArtifactID string `json:"artifact_id"`
	SessionID  string `json:"session_id,omitempty"`
	// Dir is the absolute artifact directory. Nothing outside it is served.
	Dir string `json:"-"`
	// Entry is the directory-relative default document.
	Entry     string    `json:"entry"`
	ExpiresAt time.Time `json:"expires_at"`
	// contains filtered or unexported fields
}

Grant is one artifact published for viewing.

type Options

type Options struct {
	// BaseURL resolves the origin to build absolute URLs with. It is a function
	// because the API server's bind address changes at runtime when the
	// external-access toggle is flipped. When it is nil or returns an empty
	// string the server falls back to its own loopback listener, and to a
	// relative URL when it has none.
	BaseURL func() string
	// Access is consulted on every request and before every publish. A non-nil
	// error refuses the operation. It exists so the API server can enforce
	// "never on a non-loopback bind without basic auth".
	Access func() error
	// TTL overrides DefaultTTL.
	TTL time.Duration
	// FrameAncestors overrides the CSP frame-ancestors list. It defaults to
	// 'self', which is right whenever the preview and the UI framing it share
	// an origin — the mounted deployment. A shell that runs the UI on its own
	// origin (the Wails desktop app) has to widen it, and doing that here keeps
	// the decision in the caller that knows its own origin.
	FrameAncestors string
	// Inject is JavaScript spliced into a ?bridge=1 document ahead of the
	// bridge itself. internal/design supplies the renderer's own element
	// walker here, so the data-pando-id a user clicks in the browser is the
	// same id the stored node index holds. Keeping it an option is what lets
	// this package stay ignorant of the design model.
	Inject []byte
}

Options configures a server.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the grant registry and the HTTP handler over it.

func New

func New(opts Options) *Server

New builds a server. It serves nothing until an artifact is published.

func (*Server) Addr

func (s *Server) Addr() string

Addr reports the loopback listener address, empty when there is none.

func (*Server) Bump

func (s *Server) Bump(artifactID string)

Bump increments the live-reload revision of a published artifact. It is a no-op when the artifact has no active grant on this server.

func (*Server) Close

func (s *Server) Close()

Close stops the loopback listener and drops every grant.

func (*Server) Grants

func (s *Server) Grants() []Grant

Grants lists the live grants, newest expiry first is not guaranteed; the order is unspecified. It exists for diagnostics and tests.

func (*Server) Publish

func (s *Server) Publish(artifactID, sessionID, absDir, entry string) (Grant, error)

Publish registers (or refreshes) a grant for an artifact directory and returns it. The token is stable for the lifetime of the grant so reloading a preview keeps the same URL, which is what lets an iframe survive a re-render.

func (*Server) Revoke

func (s *Server) Revoke(artifactID string)

Revoke drops the grant of one artifact.

func (*Server) RevokeSession

func (s *Server) RevokeSession(sessionID string)

RevokeSession drops every grant a session published. Sessions end; their preview URLs must stop resolving with them.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP serves artifact files under Prefix.

func (*Server) StartLoopback

func (s *Server) StartLoopback() error

StartLoopback binds 127.0.0.1:0 and serves the preview routes there. It is the fallback for processes with no API server; calling it twice is a no-op.

func (*Server) URL

func (s *Server) URL(artifactID string, opts URLOptions) (string, error)

URL returns the address of a published artifact.

type URLOptions

type URLOptions struct {
	// Slide adds a #slide-N fragment (decks).
	Slide int
	// Bridge asks for the selection bridge to be injected. Only the Pando UI
	// sets it; a URL opened in a plain browser stays untouched markup.
	Bridge bool
	// Doc overrides the entry document with another directory-relative file.
	Doc string
}

URLOptions tunes the address Publish hands out.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL