demo

package
v0.2.17 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2026 License: MPL-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package demo holds the txco demo's curriculum — the tracks, steps, and starting ops that `txco demo` seeds into a chassis at boot. The SAME data feeds two consumers:

  • chassis/cli/demo.runDemo → demo.Seed(adminURL) pre-seeds every stack against the loopback admin API before opening the browser, so the user never sees a "step failed to seed" error on first load.
  • chassis/server/admin.handleDemoCurriculum exposes the same data at GET /v1/demo/curriculum so the admin-ui Runner can render the walkthrough (titles, prose, ops, request shape) without duplicating the curriculum in TypeScript.

Single source of truth: don't add a parallel definition in admin-ui/. The SPA fetches its rendering data from the endpoint above; the seeding is done already by the time the SPA mounts.

Index

Constants

View Source
const DefaultHostSuffix = "local.thanks.computer"

DefaultHostSuffix is the wildcard DNS suffix used for all demo stack hostnames.

Variables

This section is empty.

Functions

func Seed

func Seed(ctx context.Context, adminURL string) error

Seed walks the curriculum and ensures every step's stack exists on the chassis at `adminURL`, with the step's ops as the active version and `<stack>.<HostSuffix>` bound to it.

Called from `txco demo` after the chassis is ready but before the browser opens. By the time the SPA mounts, all stacks are already seeded — the Runner's onMount filter sees them via listStacks and does nothing, so the user never sees a "step failed to seed" error.

Sequencing: stacks are seeded SERIALLY (one chain at a time). The SPA used to run 3 concurrent chains for speed; the chassis's SQLite contention story under that load was lossy (~13% of chains hit a transient 500). Serial is ~3–4 s wall-clock for ~15 stacks, which is fine here — happens once at startup, in the background of the spinner.

Best-effort per step: if a step's chain fails (createDraft, etc.), Seed logs the failure and continues. The SPA's listStacks filter will catch any stack missing an active_version on first paint and (re-)seed just those. Worst case: one transient failure → the SPA quietly retries it on first load.

Types

type Curriculum

type Curriculum struct {
	HostSuffix string  `json:"host_suffix"`
	Tracks     []Track `json:"tracks"`
}

Curriculum is the top-level shape returned by GET /v1/demo/curriculum and consumed by Seed. HostSuffix is the wildcard DNS suffix every step's bound hostname uses (e.g. `<stack>.local.thanks.computer`); the wildcard resolves to 127.0.0.1 publicly so loopback "subdomain" routing works without per-machine DNS setup.

func Get

func Get() Curriculum

Get returns the full demo curriculum. Stack names are derived (`<trackID>-<i+1>` for each step) and populated here so consumers don't have to know the convention. Returning a fresh value rather than a package-level pointer so callers (the seed loop, the HTTP handler) can mutate locally without affecting each other.

type Method

type Method string

Method is the HTTP method a step's fire uses. The same restricted set the admin-ui's TypeScript declares; serialized as the bare verb string ("GET", "POST", "PUT", "DELETE").

type OpFile

type OpFile struct {
	Name  string `json:"name"`
	Scope int    `json:"scope"`
	Txcl  string `json:"txcl"`
	Js    string `json:"js,omitempty"`
}

OpFile is one op in a step's ops list — its name, the scope it runs at (ops at the same scope run in parallel; later scopes run after), the TXCL source, and optionally a JavaScript "nano-op" compute source. When Js is non-empty the seed compiles it via the demo's /v1/demo/op/build endpoint (which bundles + javy-compiles + stores a `compute://sha256/<digest>` wasm artifact) and substitutes that ref into Txcl in place of `op://<name>` before activate. An empty-string Js (vs nil) opts the op into the SPA's JS textarea even when no source has been authored yet.

type Step

type Step struct {
	Title  string   `json:"title"`
	Prose  string   `json:"prose"`
	Ops    []OpFile `json:"ops"`
	Method Method   `json:"method"`
	Path   string   `json:"path"`
	Body   string   `json:"body,omitempty"`
	Stack  string   `json:"stack"`
}

Step is one stop on the walkthrough — a title + prose explaining what changed since the previous step, the cumulative ops list, and the request (method/path/body) to fire against it. Every step has its OWN stack (Stack), bound to `<stack>.local.thanks.computer` so tab switches are pure-navigation rather than re-applies.

type Track

type Track struct {
	ID    string `json:"id"`
	Title string `json:"title"`
	Steps []Step `json:"steps"`
}

Track groups a sequence of steps under a single ID + title. The ID is the prefix for each step's default stack name (`<id>-<i+1>`).

Jump to

Keyboard shortcuts

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