Rebrand CommGate to gsmnode and adopt new design system

Rename the whole project from CommGate to gsmnode and re-skin every
surface onto the new signal-green + ink design system (Space Grotesk /
IBM Plex Sans / JetBrains Mono, flat surfaces, two-arrow routing mark,
lowercase gsm+node wordmark).

- Web App + API panel: rewrite token layer, gn-* utilities, data-gsm-theme,
  new logo/favicon assets; both builds verified.
- Phone App (Flutter): green theme, new mark/wordmark widgets, adaptive
  launcher icons; rename Android applicationId/package to app.gsmnode.phone;
  bump AGP to 8.6.0 and google_fonts to 8.1.0; debug APK build verified.
- API Server (Go): panel routes, User-Agent, health service id, branding.
- Home Assistant Plugin: rename integration domain sms_gateway to gsmnode
  (folder, DOMAIN, services, entity ids, classes); py_compile verified.
- Update all READMEs; add .gitignore (excludes Design/, build artifacts).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81
2026-07-06 08:53:14 +02:00
commit d6956395c8
166 changed files with 12605 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
package api
import (
"encoding/json"
"errors"
"io"
"log"
"net/http"
"smsgateway/apiserver/internal/pb"
)
// writeJSON writes v as a JSON response with the given status code.
func writeJSON(w http.ResponseWriter, status int, v any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if v == nil {
return
}
if err := json.NewEncoder(w).Encode(v); err != nil {
log.Printf("writeJSON: %v", err)
}
}
// errorBody is the standard error envelope.
type errorBody struct {
Error string `json:"error"`
}
// writeError writes a JSON error response.
func writeError(w http.ResponseWriter, status int, msg string) {
writeJSON(w, status, errorBody{Error: msg})
}
// writeUpstreamError maps a PocketBase error onto an appropriate HTTP status.
func writeUpstreamError(w http.ResponseWriter, err error) {
var apiErr *pb.APIError
if errors.As(err, &apiErr) {
switch apiErr.Status {
case http.StatusNotFound:
writeError(w, http.StatusNotFound, "not found")
case http.StatusBadRequest:
writeError(w, http.StatusBadRequest, apiErr.Message)
case http.StatusForbidden:
writeError(w, http.StatusForbidden, "forbidden")
default:
log.Printf("upstream error: %v (%s)", apiErr, apiErr.Body)
writeError(w, http.StatusBadGateway, "upstream error")
}
return
}
log.Printf("internal error: %v", err)
writeError(w, http.StatusInternalServerError, "internal error")
}
// decodeJSON reads and decodes a JSON request body into v.
func decodeJSON(r *http.Request, v any) error {
defer io.Copy(io.Discard, r.Body)
dec := json.NewDecoder(http.MaxBytesReader(nil, r.Body, 1<<20))
dec.DisallowUnknownFields()
if err := dec.Decode(v); err != nil {
return err
}
return nil
}