gofastr-plugins

module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: MIT

README

gofastr-plugins

Officially-maintained heavy-JavaScript plugins for the GoFastr framework — the ones that are too big (or too client-heavy) to live in the SSR-thin, Go-pure core.

Keeping them here means the core keeps its ≤12 KB runtime budget and its minimal-dependency posture, while apps that want a fat client feature (a Rich Text editor, etc.) opt in with a single go get.

Why a separate repo

  • The GoFastr core stays pure Go with a tiny runtime. Heavy JS never enters its go.mod or its JS budget.
  • Each plugin embeds its prebuilt JS bundle via go:embed and serves it same-origin (CSP-clean). No CDN, no external <script>.
  • Plugins are treated as genuinely third-party even though first-party- maintained: they run isolated (sandboxed iframe), talk to the host only over a versioned postMessage capability bridge, and cannot reach host cookies, the DB, or the host DOM. See docs/PLAN.md.

Layout

gofastr-plugins/
├── pluginhost/   the reusable platform: Manifest, AssetServer, Allow,
│                 MountMarker, broker — distilled from the editor
├── richtext/      the ProseMirror block editor plugin (#1) + ssr/ read renderer
├── mermaid/      the Mermaid diagram plugin (#2, the completeness canary)
├── example/      ONE gofastr app that imports & mounts every plugin —
│                 the integration host, visual/e2e surface, completeness canary
├── plugins.json  the curated registry index (convention, not a service) —
│                 hosts fetch and vendor this file; see "The registry" below
├── docs/         PLAN.md, DECISIONS.md, design/ (frozen) + platform/plugin docs
└── CHANGELOG.md

The registry

plugins.json at the repo root is the curated index — a convention, not a service. There is no runtime discovery: apps import a plugin package directly via its modulePath and mount it with framework.RegisterPlugin.

It is consumed by copy, not by import. A host — GoFastr's docs site first — fetches the file at deploy time, vendors it, and generates a page per plugin from it. The published artifact is the JSON, so this repo deliberately exposes no Go API for it: nothing to import means no module cycle (GoFastr would otherwise be importing a repo that imports GoFastr) and no route by which chromedp or an embedded JS bundle reaches the core's go.mod.

Tagging vX.Y.Z publishes a release with plugins.json attached (.github/workflows/release.yml), so hosts fetch it from a stable URL:

# Pinned to a known release — what a reproducible deploy should use.
curl -fsSL -O https://github.com/DonaldMurillo/gofastr-plugins/releases/download/v0.1.0/plugins.json

# Or always the newest release.
curl -fsSL -O https://github.com/DonaldMurillo/gofastr-plugins/releases/latest/download/plugins.json

The published copy carries a release stamp (tag, commit, timestamp, source) that the file in git does not — the release workflow adds it on the way out. That is what keeps a vendored copy honest: without it, a year-old plugins.json sitting in a host repo looks exactly like a fresh one. A test asserts the committed file has no stamp, since a hand-written one would be a lie the moment it landed.

The index is hand-maintained, so internal/registry guards the drift nothing else would catch: rows must cover exactly the plugin packages in the repo, each routePrefix must equal that package's own const, no row may request allow-same-origin, and the parser rejects unknown fields — a new key must reach the structs in the same change rather than being silently dropped. Those guards run again inside the release workflow, so a broken index cannot reach a host. Bump registryVersion on a breaking field change, since vendored copies are then stale.

Develop

This repo pins a published GoFastr release (require github.com/DonaldMurillo/gofastr vX.Y.Z), so a fresh clone builds with nothing but go build ./... — no sibling checkout required.

To edit both repos in one loop, use a Go workspace instead of a committed replace directive. go.work is gitignored, so your local wiring never leaks into what everyone else builds:

go work init . ../gofastr    # once
go run ./example

Verify a change the way a consumer sees it — resolving GoFastr from the module proxy rather than your checkout:

GOWORK=off go build ./...

Testing

Two layers, because this project is UI-heavy and engine differences are real (several shipped bugs were Safari-only and invisible to Chrome-based tests):

  • Go suite (go test ./...) — unit + integration + headless-Chrome checks of isolation, latency, round-tripping, and rendering.
  • User-journey e2e (cd e2e && npm test) — Playwright drives the editor the way a person does (real clicks, typing, slash-menu selection, toolbar) in WebKit (Safari's engine) and Chromium, against both mounts: the default sandboxed iframe and the explicit trusted in-page opt-out (richtext.WithTrustedMount(), demo at /__gofastr/plugin/richtext/trusted). Any console/page error fails the test. npm run test:headed watches a run live.

Status

Phase 0 — the isolation spike — is built and the gate cleared: an opaque- origin sandboxed ProseMirror measured p99 keystroke latency 8.6 ms (target ≤ 16 ms), proven isolated from both sides. The platform glue is extracted into pluginhost, the editor + a pure-Go SSR read view ship, and a second plugin (mermaid) proves the platform generalizes. See CHANGELOG.md and docs/.

Directories

Path Synopsis
Command example is the single GoFastr app that imports and mounts every plugin in this repo.
Command example is the single GoFastr app that imports and mounts every plugin in this repo.
internal
registry
Package registry defines the schema of the curated plugin index and keeps it honest.
Package registry defines the schema of the curated plugin index and keeps it honest.
Package pluginhost re-exports the GoFastr heavy-JS plugin platform.
Package pluginhost re-exports the GoFastr heavy-JS plugin platform.
Package richtext is a full Rich Text block editor plugin for GoFastr, built on ProseMirror and delivered as a genuinely third-party, isolated heavy-JS plugin.
Package richtext is a full Rich Text block editor plugin for GoFastr, built on ProseMirror and delivered as a genuinely third-party, isolated heavy-JS plugin.
ssr
Package ssr renders canonical Rich Text block-JSON (a ProseMirror doc, schema version "richtext-v1") into design-token HTML for the no-JS first paint.
Package ssr renders canonical Rich Text block-JSON (a ProseMirror doc, schema version "richtext-v1") into design-token HTML for the no-JS first paint.

Jump to

Keyboard shortcuts

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