From 4e2a9c86051ad76048e0c00a07d4bcc473e8ced8 Mon Sep 17 00:00:00 2001 From: felipegenef Date: Fri, 10 Jul 2026 20:52:22 -0300 Subject: [PATCH] =?UTF-8?q?v2.18.0:=20final=20v2=20=E2=80=94=20migrate-v3?= =?UTF-8?q?=20bridge=20to=20github.com/gothicframework=20+=20README=20redi?= =?UTF-8?q?rect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- README.md | 84 +++++++++++------------- cmd/migrate_v3.go | 145 +++++++++++++++++++++++++++++++++++++++++ cmd/migrate_v3_test.go | 61 +++++++++++++++++ cmd/version.go | 2 +- 5 files changed, 248 insertions(+), 47 deletions(-) create mode 100644 cmd/migrate_v3.go create mode 100644 cmd/migrate_v3_test.go diff --git a/.gitignore b/.gitignore index 79873cf..97a6005 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ main main.exe gothicframework gothicframework.exe -.claude/ \ No newline at end of file +.claude/ +coverage.out \ No newline at end of file diff --git a/README.md b/README.md index a803a31..ab23664 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,63 @@ -background doc +Gothic Framework -[![CI](https://github.com/felipegenef/gothicframework/actions/workflows/ci.yml/badge.svg)](https://github.com/felipegenef/gothicframework/actions/workflows/ci.yml) -[![codecov](https://codecov.io/gh/felipegenef/gothicframework/branch/main/graph/badge.svg)](https://codecov.io/gh/felipegenef/gothicframework) +# Gothic Framework has moved 🚚 - - -## πŸš€ Build Modern Web Apps with Ease - -**Gothic Framework** is a developer-first toolset built to help you craft fast, scalable, and modern web applications using the **GOTTH stack**: -**Golang**, **TailwindCSS**, **Templ**, and **HTMX**. - -Inspired by frameworks like **Next.js**, Gothic Framework brings powerful full-stack features to Go developers β€” including edge-ready architecture, SEO enhancements, and a fantastic development experience (DX). - -[![See our docs](https://img.shields.io/badge/See_our_docs-ec4899?style=for-the-badge)](https://gothicframework.com) +**Gothic Framework** is a developer-first toolset for building fast, scalable, modern web apps in Go with the **GOTTH stack** β€” **Go**, **TailwindCSS**, **Templ**, and **HTMX**. --- -## 🧠 Why Gothic? +## Where everything lives now (v3) -Gothic Framework was built to make **Go-based web development** simpler, faster, and more productive without sacrificing performance or modern UX standards. +| Module | Repo | What it is | +|---|---|---| +| **CLI** | [`gothicframework/cli`](https://github.com/gothicframework/cli) | The `gothic` command (scaffold, dev, build, deploy) | +| **Core** | [`gothicframework/core`](https://github.com/gothicframework/core) | Runtime library: file-based routing, caching/ISR, WASM runtime, assets | +| **Components** | [`gothicframework/components`](https://github.com/gothicframework/components) | Reusable Templ components (`RuntimeScripts`, `Styles`, `OptimizedImage`, …) | +| **Middlewares** | [`gothicframework/middlewares`](https://github.com/gothicframework/middlewares) | The single chi middleware that wires the whole runtime | -Whether you're launching a SaaS, building internal tools, or prototyping something new β€” Gothic Framework has your back. +### Install the v3 CLI ---- - -## βš™οΈ Effortless Deployment, Powerful Infrastructure +```bash +go install github.com/gothicframework/cli/v3/cmd/gothic@latest +gothic init github.com/you/my-app +``` -Gothic Framework comes with built-in AWS SAM integration, making deployment to the cloud **as simple as a single command**. Focus on your app’s features and logic β€” not on cloud setup or DevOps headaches. - - +The libraries version independently of the CLI β€” you never add them by hand. `gothic init` scaffolds a project that imports them at the right versions. --- -## πŸ”₯ Features Inspired by Next.js - -### πŸ–ΌοΈ SEO-Optimized Image Loading -Like the Next.js Image component, Gothic Framework lazy-loads images for better performance and user experience. A low-res placeholder is swapped with the full image after load β€” smooth and fast. +## Already on v2? Migrate in one command -### 🌐 Static CDN Caching -Static pages can be cached at **CloudFront edge locations** for blazing-fast performance β€” with cache TTLs of up to **1 year**! +From your existing v2 project root, using this (final) v2 CLI: -### ♻️ Incremental Static Regeneration (ISR) -Rebuild only the parts of your app that change. Gothic Framework lets you specify revalidation intervals β€” from seconds to **a full year**. +```bash +gothicframework migrate-v3 +``` -### πŸ™…β€β™€οΈ Custom 404 Pages -Craft personalized 404 pages to guide users gracefully when something goes missing. +That command installs the new `gothic` CLI, runs the migration for you, and then hands you over to the new command name. Equivalently, if you already installed the v3 CLI: -### ⚑ Link Prefetching -Just like in Next.js, Gothic Framework prefetches pages on **mouseover** so they load instantly on click. That’s snappy navigation! +```bash +go install github.com/gothicframework/cli/v3/cmd/gothic@latest +gothic migrate-v3 # add --dry-run to preview +``` -### πŸ” Hot Reloading -Make a change, save, and see it live instantly. No rebuilds. No restarts. Just code. +After migrating, use **`gothic`** instead of **`gothicframework`**: -### πŸ“‘ API Routes with JSON -Define backend logic with ease. Gothic Framework supports API routes for JSON payloads out of the box β€” perfect for building APIs alongside your frontend pages. +| Before (v2) | After (v3) | +|---|---| +| `gothicframework dev` | `gothic dev` | +| `gothicframework build` | `gothic build` | +| `gothicframework deploy` | `gothic deploy` | -### 🧩 File-Based Routing -Drop your components into `/pages`, `/components`, or `/api` β€” and Gothic automatically maps them to routes. Simple and intuitive. +See the **[v3 CLI repo](https://github.com/gothicframework/cli)** for the full list of breaking changes and new features (OpenTofu-based deploys, Go-based config, the rearchitected WASM runtime, and more). --- -## πŸ§ͺ Try Gothic Today +## v1 / v2 reference -Take your Go projects to the next level with a framework that speaks your language and supports modern best practices. +The last v2 release (**v2.18.0**) is this repository at its final state: the full v2 toolchain **plus** the `migrate-v3` bridge above. Older tags remain available for historical reference. For anything new, start with the [v3 CLI](https://github.com/gothicframework/cli). diff --git a/cmd/migrate_v3.go b/cmd/migrate_v3.go new file mode 100644 index 0000000..26db3a3 --- /dev/null +++ b/cmd/migrate_v3.go @@ -0,0 +1,145 @@ +/* +Copyright Β© 2025 NAME HERE +*/ +package cmd + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + + "github.com/spf13/cobra" +) + +// newCLIInstallPath is the `go install` target for the v3 CLI. Gothic v3 no +// longer lives in this repository (github.com/felipegenef/gothicframework); it +// was split into github.com/gothicframework/* and the binary was renamed +// gothicframework -> gothic. This last v2 release only bridges to it. +const newCLIInstallPath = "github.com/gothicframework/cli/v3/cmd/gothic@latest" + +var ( + migrateV3DryRun bool + migrateV3Path string +) + +// migrateV3Cmd is a BRIDGE, not an in-process migration. The real v2->v3 +// migration logic lives in the new `gothic` binary; this command installs that +// binary and delegates to it, then tells the user the command name changed. +var migrateV3Cmd = &cobra.Command{ + Use: "migrate-v3", + Short: "Migrate this project to Gothic v3 (new github.com/gothicframework repo + gothic CLI)", + Long: `Gothic v3 moved to a new home: github.com/gothicframework, and the CLI was +renamed from "gothicframework" to "gothic". + +This command bridges you there. It: + + 1. Installs the v3 CLI: go install ` + newCLIInstallPath + ` + 2. Runs: gothic migrate-v3 [--dry-run] [--path ] + 3. From here on, you use "gothic" instead of "gothicframework". + +The actual migration is performed by the new gothic binary, so it always +reflects the latest v3 conversion logic.`, + RunE: func(cmd *cobra.Command, args []string) error { + return runMigrateV3Bridge() + }, +} + +func init() { + migrateV3Cmd.Flags().BoolVar(&migrateV3DryRun, "dry-run", false, "Preview the migration without writing files") + migrateV3Cmd.Flags().StringVar(&migrateV3Path, "path", ".", "Project root to migrate") + rootCmd.AddCommand(migrateV3Cmd) +} + +func runMigrateV3Bridge() error { + fmt.Println("β–Έ Gothic v3 moved to github.com/gothicframework β€” installing the new 'gothic' CLI…") + fmt.Printf(" go install %s\n\n", newCLIInstallPath) + + // 1. Install the new gothic CLI. + install := exec.Command("go", "install", newCLIInstallPath) + install.Stdout = os.Stdout + install.Stderr = os.Stderr + install.Env = os.Environ() + if err := install.Run(); err != nil { + return fmt.Errorf("failed to install the new gothic CLI (%s): %w\n"+ + "If the new repositories are private, make sure your git/GOPRIVATE access is configured.", newCLIInstallPath, err) + } + + // 2. Locate the freshly installed binary. + gothicBin, err := locateGothic() + if err != nil { + return err + } + + // 3. Delegate the real migration to the new binary, forwarding our flags. + delegated := []string{"migrate-v3"} + if migrateV3DryRun { + delegated = append(delegated, "--dry-run") + } + if migrateV3Path != "" && migrateV3Path != "." { + delegated = append(delegated, "--path", migrateV3Path) + } + fmt.Printf("\nβ–Έ Running: gothic %s\n\n", strings.Join(delegated, " ")) + run := exec.Command(gothicBin, delegated...) + run.Stdout = os.Stdout + run.Stderr = os.Stderr + run.Stdin = os.Stdin + run.Env = os.Environ() + if err := run.Run(); err != nil { + return fmt.Errorf("gothic migrate-v3 failed: %w", err) + } + + // 4. The command name changed β€” make sure the user knows. + fmt.Println() + fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") + fmt.Println(" βœ“ Migrated to Gothic v3") + fmt.Println() + fmt.Println(" From now on use the new CLI: 'gothic' (not 'gothicframework')") + fmt.Println(" gothic dev # was: gothicframework dev") + fmt.Println(" gothic build # was: gothicframework build") + fmt.Println(" gothic deploy # was: gothicframework deploy") + fmt.Println() + fmt.Println(" If 'gothic' isn't found, add your Go bin dir to PATH:") + fmt.Println(" export PATH=\"$PATH:$(go env GOPATH)/bin\"") + fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") + return nil +} + +// locateGothic finds the gothic binary installed by `go install`, preferring the +// PATH, then GOBIN, then GOPATH/bin. +func locateGothic() (string, error) { + bin := "gothic" + if runtime.GOOS == "windows" { + bin = "gothic.exe" + } + if p, err := exec.LookPath(bin); err == nil { + return p, nil + } + if gobin := goEnv("GOBIN"); gobin != "" { + if p := filepath.Join(gobin, bin); fileExists(p) { + return p, nil + } + } + if gopath := goEnv("GOPATH"); gopath != "" { + if p := filepath.Join(gopath, "bin", bin); fileExists(p) { + return p, nil + } + } + return "", fmt.Errorf("installed the new CLI but couldn't find the '%s' binary on PATH; "+ + "add \"$(go env GOPATH)/bin\" to your PATH and run 'gothic migrate-v3'", bin) +} + +func goEnv(key string) string { + out, err := exec.Command("go", "env", key).Output() + if err != nil { + return "" + } + return strings.TrimSpace(string(out)) +} + +func fileExists(p string) bool { + info, err := os.Stat(p) + return err == nil && !info.IsDir() +} diff --git a/cmd/migrate_v3_test.go b/cmd/migrate_v3_test.go new file mode 100644 index 0000000..21dfd52 --- /dev/null +++ b/cmd/migrate_v3_test.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "testing" +) + +func TestMigrateV3FileExists(t *testing.T) { + dir := t.TempDir() + f := filepath.Join(dir, "x") + if err := os.WriteFile(f, []byte("hi"), 0o644); err != nil { + t.Fatal(err) + } + if !fileExists(f) { + t.Errorf("fileExists(%q) = false, want true", f) + } + if fileExists(filepath.Join(dir, "missing")) { + t.Error("fileExists on a missing file = true, want false") + } + if fileExists(dir) { + t.Error("fileExists on a directory = true, want false") + } +} + +func TestMigrateV3GoEnv(t *testing.T) { + got := goEnv("GOPATH") + if got == "" { + t.Fatal("goEnv(GOPATH) = empty, want a path") + } + if got != strings.TrimSpace(got) { + t.Errorf("goEnv(GOPATH) not trimmed: %q", got) + } +} + +// TestMigrateV3LocateGothicOnPath puts a fake `gothic` first on PATH and asserts +// locateGothic resolves it via exec.LookPath. +func TestMigrateV3LocateGothicOnPath(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("exec-bit / .exe resolution differs on Windows") + } + dir := t.TempDir() + bin := filepath.Join(dir, "gothic") + if err := os.WriteFile(bin, []byte("#!/bin/sh\n"), 0o755); err != nil { + t.Fatal(err) + } + t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH")) + + got, err := locateGothic() + if err != nil { + t.Fatalf("locateGothic: %v", err) + } + if filepath.Base(got) != "gothic" { + t.Errorf("locateGothic() = %q, want a path ending in 'gothic'", got) + } + if !fileExists(got) { + t.Errorf("locateGothic() returned a non-existent path %q", got) + } +} diff --git a/cmd/version.go b/cmd/version.go index 63347bc..7fa56ae 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" ) -var CURRENT_VERSION string = "v2.17.4" +var CURRENT_VERSION string = "v2.18.0" // versionCmd represents the version command var versionCmd = &cobra.Command{