Records the move from Scala to Go, the compiled-plugin decision, the Płytarium port as the v1 target, and the Go ecosystem research that backs the choice. No code yet.
7.2 KiB
7.2 KiB
title, date, source
| title | date | source |
|---|---|---|
| Go ecosystem viability for SummerCMS | 2026-09-16 | Research pass during the opening exploration session. Stars and last-push dates verified via GitHub API on 2026-09-16 unless tagged [ASSUMED]. |
Go ecosystem viability report (WinterCMS -> Go)
Verdict: the "Go is closer to PHP's richness" bet holds for every concern except the plugin model, and that has a proven answer (section 2).
1. Ecosystem coverage
| Concern | Pick (stars, last push) | Runner-up | Maturity note |
|---|---|---|---|
| HTTP router | net/http ServeMux (stdlib; method and wildcard patterns since 1.22) | chi 22.8k (09-2026) | stdlib mux is enough for a CMS; chi adds middleware groups and stays net/http-compatible. gin 89k, echo 32.7k, fiber 40k are alive but use non-stdlib handler types; fiber (fasthttp) breaks stdlib middleware. Avoid. |
| ORM / query | ent 17.2k (09-2026) or GORM 40k (09-2026) | bun 5k, sqlc 18.3k | ent = schema-as-code + codegen, best fit for YAML-driven form generation and migrations. GORM = closest to Eloquent DX, weaker typing. sqlx 17.7k last push 2024-08, stagnant. |
| Migrations | goose 11.5k (09-2026) | golang-migrate 18.9k, atlas 8.7k | goose supports Go-code migrations (needed for plugin migrations). atlas pairs with ent for declarative diff. |
| OAuth2 / OIDC server | zitadel/oidc 1.9k (09-2026), OP+RP, OpenID-certified | go-oauth2/oauth2 3.6k (09-2026, RFC 6749 only, no OIDC) | This is the Scala gap, closed. ory/fosite 2.6k last push 2025-11; Ory pushes users to Hydra. Reference only. |
| JWT | golang-jwt/jwt 9.2k (09-2026) | De facto standard. | |
| Sessions | alexedwards/scs 2.6k (11-2025) | gorilla/sessions 3.2k (08-2024) | scs is server-side with pluggable stores (pg, redis, sqlite). gorilla is cookie-signed and dormant. |
| Validation | go-playground/validator 20.2k (09-2026) | Tag-based, i18n error messages, maps well to YAML rules:. |
|
| Config | koanf 4.2k (09-2026) | viper 30.5k (01-2026) | koanf is lighter with fewer deps. Either fine. |
| CLI | cobra 44.6k (07-2026) | urfave/cli 24.2k (09-2026) | cobra for summer make:plugin-style scaffolding. |
| Templates | html/template (stdlib) + templ 10.5k (09-2026) for typed components | pongo2 3.1k (05-2026) for Twig syntax | pongo2 gives theme authors Twig-like syntax (WinterCMS parity) but is single-maintainer. Use it only for themes, not admin. |
| i18n | go-i18n 3.5k (09-2026) | spreak 94 stars | go-i18n is CLDR-plural, standard. |
| Queue / jobs | river 5.7k (09-2026, Postgres/SQLite, transactional) | asynq 13.7k (06-2026, Redis) | river avoids a Redis dependency. |
| Cache | otter 2.7k (06-2026) in-memory; go-redis 22.2k (09-2026) | ristretto 7k (09-2026) | otter v2 is W-TinyLFU, faster than ristretto per maintainers' benchmarks [ASSUMED]. |
| wneessen/go-mail 1.5k (09-2026) | Active, SMTP auth variants, no deps. | ||
| Events / pubsub | In-process: hand-rolled typed bus with generics | watermill ~8k [ASSUMED] for cross-process | No dominant in-process event lib. It is ~200 LOC. |
| WebSockets | coder/websocket 5.5k (06-2026) | gorilla/websocket 24.9k (03-2025) | coder is context-aware and wasm-capable. gorilla maintained but quiet. |
| File storage | gocloud.dev/blob 9.9k (09-2026) | afero 6.7k (09-2026) | blob = S3/GCS/Azure/local behind one API (Flysystem equivalent). afero for FS mocking. |
2. Plugin architecture (key risk)
| Approach | Real project | DX | Verdict |
|---|---|---|---|
| (a) Compile-time registration + custom build | Caddy + xcaddy 1.5k (08-2026); Grafana core; Hugo | Plugin = Go module with init() registering into a registry. summer build --with github.com/x/plugin rebuilds the binary. |
Recommended. Full type safety, zero runtime overhead, plugins extend each other via normal Go interfaces, go test works. Pain: rebuild required (seconds), Go toolchain at deploy or in CI. |
(b) stdlib plugin |
almost nobody in prod | Linux/macOS only, host and plugin must share exact toolchain and dep versions, no unload, panic kills host | Reject. Docs still say "known to have a number of issues". |
| (c) RPC subprocess | hashicorp/go-plugin 6.1k (09-2026); Grafana backend plugins; Terraform | Each plugin a separate binary over gRPC, 30-50us per call | Good for isolation, wrong for a CMS where plugins register models, form fields, components, and extend each other. Surface too wide to marshal. |
| (d) WASM | extism 5.8k (09-2026) on wazero (~5k [ASSUMED]) | Sandboxed, polyglot, hot-reloadable | Same interface-width problem as (c), plus no direct DB/ORM access from guest. Suitable only for untrusted marketplace "widgets". |
| (e) Interpreter | traefik/yaegi 8.4k, last push 02-2026, README targets Go 1.21/1.22 | Drop source in folder, runs at startup. Traefik vendors deps because yaegi has no module support. | Lagging Go releases badly, partial generics, no cgo, slower. Traefik plugins are tiny middlewares, not CMS plugins. |
Recommendation: (a) as the primary mechanism, mirroring xcaddy: plugins/ dir of Go modules, a generated plugins.go import list, summer plugin:add / make:plugin commands that scaffold, rewrite go.mod (replace directive for local dev) and rebuild. Add an air/reflex-style watch-rebuild for dev to feel like WinterCMS's drop-in loop. Keep an optional (d) WASM slot later for untrusted extensions. This is what Hugo, Caddy, Grafana core, Mattermost (partly), and Gitea converged on.
3. Existing Go frameworks and CMSes
| Project | Status | Steal | Base or reference |
|---|---|---|---|
| Goravel (framework 524 stars, skeleton 4.8k, 09-2026) | Alive, active issues 2026 | Facade layer, artisan-style CLI, Laravel-shaped config/queue/mail abstractions | Reference only. Small core team, own ORM wrapper, coupled to its facades. |
| GoFrame 13.3k (09-2026) | Alive, Chinese-led | gf gen codegen (dao/model/ctrl), gi18n, config, ORM |
Reference. Monolithic, non-idiomatic. |
| Beego 32.4k (09-2026) | Alive but legacy | Little; MVC only | Reference. |
| Buffalo 8.4k | Archived Feb 2024; API shows unarchived, push 03-2026 (unclear) | pop ORM migrations, plush templates, generators |
Dead for basing. |
| PocketBase 61k (09-2026) | Very alive; "standalone app or Go framework"; SQLite; hooks + JS VM (goja) plugin | Hook/event system, collection-schema-driven admin UI, Go-framework-mode API | Best reference for schema-driven admin forms. Not a base (SQLite-only, no plugin packaging, single maintainer). |
| Fastschema 571 (07-2026) | Beta | ent-backed schema-to-CRUD, plugin system | Reference. Too small. |
| Ponzu 5.8k | Abandoned (README says so) | Nothing | Dead. |
4. Go 1.27 (Aug 2026) notes
- Generic methods landed (methods may declare their own type params, not on interfaces). Cleans up repository and query-builder APIs.
encoding/jsonnow backed by json/v2: faster, stricter (rejects duplicate keys and invalid UTF-8). Relevant to YAML/JSON form definitions.- Iterators (
range over func,iterpkg) stable since 1.23. Use for paginated model queries. - net/http ServeMux method and wildcard patterns stable since 1.22. 1.27 adds RFC 9218 HTTP/2 priority.
- No change to
pluginpackage limitations.
Flags
- wazero star count unverified.
- Buffalo archived-status contradiction (web says archived 2024, API says not).
- otter-vs-ristretto performance claim is from maintainer benchmarks, not independently verified.