| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
bottle gives a tab an operating system — a filesystem, a network, processes. shipwright gives it the Go toolchain. shipyard is where you sit down and use them: a shell where you type go build, on the same in-memory filesystem the compiler reads, with the browser to view what you make.
Live demo — go is already on the PATH; type cd /work && go build . and run what comes out, or click a demo to watch it break a Go Playground limitation.
The pieces, and who does what:
A terminal window where you type go build. shipyard opens a websh terminal in a desk window, its shell running over afero.NewOsFs() — which on js/wasm is bottle's jsfs — with go on its PATH. The terminal is a registered desk app rather than a window opened once at boot, so the Applications menu opens another one and the panel keeps a button for each: closing the terminal is no longer the end of the session.
Because the shell and the toolchain share one filesystem, and websh execs a filesystem program as a child wasm process through bottle's proc, the toolchain runs as an ordinary command you type at the prompt:
$ go version go version go1.27.0 js/wasm $ go env GOROOT /goroot $ cd /work && go build -o hello.wasm . # compiles fmt/os/runtime from source $ go install github.com/0magnet/websh/cmd/websh@main # fetches + builds a whole tool
The last line is not hypothetical — shipwright already compiles websh from its whole module graph, fetched over a /goproxy passthrough. In shipyard you type it at a prompt.
index.html is the desk: it seeds the toolchain into jsfs, opens the terminal window, and lets you type. Open it with #selftest and it runs the whole demo gallery headlessly, checking each marker — the headless proof. demo.html is the same wiring without a window (the shell driven through a JS call), kept as the minimal read. Build and serve with ./build.sh (see below).
The desk carries a launcher dock (top right, on both index.html and the static Pages pages.html) of small self-contained Go programs, each demonstrating a capability the Go Playground fundamentally lacks and each captioned with the limitation it breaks. Every one runs fully client-side: no server, no /fetch, no /goproxy, no /std — so all of them work on static GitHub Pages. demos.js is the single source of truth (the gallery UI and the #selftest harness share it), and each demo confirms its own SHIPYARD-<CAP>-MARKER line:
| Demo | The Playground limitation it breaks |
|---|---|
| Filesystem (fs.wasm) | no filesystem — nowhere to write a file |
| Persistence (jsfs.persist) | keeps nothing; every run starts from scratch — here a file survives a page reload via IndexedDB |
| Processes & pipes (procparent.wasm + child) | can't spawn a process — no child, no pipe, no exit code |
| Real clock & concurrency (timeconc.wasm) | fakes the clock and caps goroutine time — here goroutines finish in real order on the real wall clock |
| Shell: stdin + pipes + jq | no stdin and no shell — here echo … | jq is a real pipeline |
| Go client ↔ Go server over vnet (netclient.wasm) | no network at all — here a Go net/http client fetches from a Go net/http server, both in-tab, over bottle's virtual loopback |
| Browse an in-tab server (netscrape) | can't run a server, a browser, or a network — here the Go/wasm browser renders a page the in-tab server serves over vnet |
| Graphical animated window (gui.wasm) | text-stdout only — here a Go program draws an animated clock on a <canvas> |
| Compile & run Go in the tab | compiles one file server-side — here go build runs in the tab and the result runs too |
| Compile & run a test (go test -c) | runs a program, not a test binary — here the toolchain compiles a test binary and proc runs it to PASS |
The programs live in one self-contained module (demo/, module demo) whose only non-std imports are its own copies of bottle's vnet and proc drop-ins, so each builds offline from the seeded standard library. Their source is seeded at /work/demo, viewable and rebuildable in the desk:
cd /work/demo && go build -o /work/server.wasm ./server && run server.wasm
websh's exec handler, on js/wasm, resolves an unknown command against the filesystem PATH and — if it finds a program — spawns it as a child wasm instance via globalThis.proc.spawn, sharing this tab's jsfs and vnet. The child's stdout/stderr cross through jsfs pipes (plain JS sinks, drained into the shell after the child exits), so nothing re-enters the shell's Go runtime mid-execution. go is just go-proc.wasm parked at /bin/go; running it is instantiating another wasm module.
./build.sh # builds shipyard.wasm + pulls shipwright's toolchain into web/ go run ./serve # http://localhost:8931, static + the /goproxy passthrough
Then open http://localhost:8931/demo.html.
Made with goda:
# GOOS=js: the import edges of a wasm program live in js/wasm-tagged # files and are invisible to a host-context run GOOS=js GOARCH=wasm go run github.com/loov/goda@latest graph github.com/0magnet/shipyard/... | dot -Tsvg -o docs/shipyard-goda-graph.svg
Made with gocloc (excludes vendor/, node_modules/, .git/):
gocloc --not-match-d='(vendor|node_modules|\.git)' .
------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Go 16 130 254 908 JavaScript 1 12 40 254 HTML 3 27 53 207 Markdown 1 22 0 114 Bourne Shell 2 16 39 103 YAML 1 0 7 98 ------------------------------------------------------------------------------- TOTAL 24 207 393 1684 -------------------------------------------------------------------------------
| Back | FazBrowse Home | New Git URL |